From 5e1927016fc99af3eecddf74352dcd8d52a4cf55 Mon Sep 17 00:00:00 2001 From: Franck Date: Thu, 25 Mar 2021 23:45:36 -0700 Subject: [PATCH] Deploy 16 (#585) * rinkeby deploy 16 * Do not kill the zombie contract * mainnet deploy 16 * Add a hardhat task to transfer money --- .../deployments/mainnet/.migrations.json | 3 +- contracts/deployments/mainnet/Buyback.json | 255 ++ .../deployments/mainnet/OracleRouter.json | 64 + contracts/deployments/mainnet/VaultAdmin.json | 173 +- contracts/deployments/mainnet/VaultCore.json | 40 +- .../cca309778b0bcb384ba7e2e97bde53a0.json | 317 ++ .../deployments/rinkeby/.migrations.json | 3 +- contracts/deployments/rinkeby/Buyback.json | 255 ++ .../deployments/rinkeby/OracleRouter.json | 64 + contracts/deployments/rinkeby/VaultAdmin.json | 173 +- contracts/deployments/rinkeby/VaultCore.json | 40 +- .../86605db9d81ca0a1790de251140fb0d9.json | 311 ++ contracts/hardhat.config.js | 7 +- contracts/storageLayout/mainnet/Buyback.json | 15 + .../storageLayout/mainnet/OracleRouter.json | 4 + .../storageLayout/mainnet/VaultAdmin.json | 16 +- .../storageLayout/mainnet/VaultCore.json | 16 +- contracts/tasks/account.js | 49 + contracts/tasks/debug.js | 4 +- dapp/network.mainnet.json | 484 ++- dapp/network.rinkeby.json | 484 ++- dapp/prod.network.json | 3659 ++++++++++------- 22 files changed, 4388 insertions(+), 2048 deletions(-) create mode 100644 contracts/deployments/mainnet/Buyback.json create mode 100644 contracts/deployments/mainnet/OracleRouter.json create mode 100644 contracts/deployments/mainnet/solcInputs/cca309778b0bcb384ba7e2e97bde53a0.json create mode 100644 contracts/deployments/rinkeby/Buyback.json create mode 100644 contracts/deployments/rinkeby/OracleRouter.json create mode 100644 contracts/deployments/rinkeby/solcInputs/86605db9d81ca0a1790de251140fb0d9.json create mode 100644 contracts/storageLayout/mainnet/Buyback.json create mode 100644 contracts/storageLayout/mainnet/OracleRouter.json diff --git a/contracts/deployments/mainnet/.migrations.json b/contracts/deployments/mainnet/.migrations.json index b48944ec97..df47397523 100644 --- a/contracts/deployments/mainnet/.migrations.json +++ b/contracts/deployments/mainnet/.migrations.json @@ -12,5 +12,6 @@ "012_upgrades": 1612303613, "013_trustee": 1612380836, "014_3pool_strategy": 1612999718, - "015_flipper": 1613166856 + "015_flipper": 1613166856, + "016_chainlink_and_buyback": 1616629649 } \ No newline at end of file diff --git a/contracts/deployments/mainnet/Buyback.json b/contracts/deployments/mainnet/Buyback.json new file mode 100644 index 0000000000..488442dba3 --- /dev/null +++ b/contracts/deployments/mainnet/Buyback.json @@ -0,0 +1,255 @@ +{ + "address": "0x7294CD3C3eb4097b03E1A61EB2AD280D3dD265e6", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "uniswapAddr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claimGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "swap", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setUniswapAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isGovernor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultAddr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "UniswapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "PendingGovernorshipTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "GovernorshipTransferred", + "type": "event" + } + ], + "transactionHash": "0x78f60a2f86398478ec514755b438717e8c522fbd22387e25df5efe1d22f96c75", + "receipt": { + "to": null, + "from": "0x71F78361537A6f7B6818e7A760c8bC0146D93f50", + "contractAddress": "0x7294CD3C3eb4097b03E1A61EB2AD280D3dD265e6", + "transactionIndex": 98, + "gasUsed": "885267", + "logsBloom": "0x0000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000100000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc82919e42dddf9ad7e7f132ddf5ec2cdd8d4947d66e8a687924e6923ca96ad76", + "transactionHash": "0x78f60a2f86398478ec514755b438717e8c522fbd22387e25df5efe1d22f96c75", + "logs": [ + { + "transactionIndex": 98, + "blockNumber": 12104656, + "transactionHash": "0x78f60a2f86398478ec514755b438717e8c522fbd22387e25df5efe1d22f96c75", + "address": "0x7294CD3C3eb4097b03E1A61EB2AD280D3dD265e6", + "topics": [ + "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000071f78361537a6f7b6818e7a760c8bc0146d93f50" + ], + "data": "0x", + "logIndex": 146, + "blockHash": "0xc82919e42dddf9ad7e7f132ddf5ec2cdd8d4947d66e8a687924e6923ca96ad76" + } + ], + "blockNumber": 12104656, + "cumulativeGasUsed": "6026783", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "cca309778b0bcb384ba7e2e97bde53a0", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"swap\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setUniswapAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"setUniswapAddr(address)\":{\"details\":\"Set address of Uniswap for performing liquidation of strategy reward tokens. Setting to 0x0 will pause swaps.\",\"params\":{\"_address\":\"Address of Uniswap\"}},\"swap()\":{\"details\":\"Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible protocol (e.g. Sushiswap)*\"},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}}}},\"userdoc\":{\"methods\":{\"transferToken(address,uint256)\":{\"notice\":\"Owner function to withdraw a specific amount of a token\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/buyback/Buyback.sol\":\"Buyback\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"contracts/buyback/Buyback.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\nimport { IUniswapV2Router } from \\\"../interfaces/uniswap/IUniswapV2Router02.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\ncontract Buyback is Governable {\\n using SafeERC20 for IERC20;\\n\\n event UniswapUpdated(address _address);\\n\\n // Address of Uniswap\\n address public uniswapAddr = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;\\n\\n // Address of OUSD Vault\\n address constant public vaultAddr = 0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70;\\n\\n // Swap from OUSD\\n IERC20 constant ousd = IERC20(0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86);\\n\\n // Swap to OGN\\n IERC20 constant ogn = IERC20(0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26);\\n\\n // USDT for Uniswap path\\n IERC20 constant usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);\\n\\n /**\\n * @dev Verifies that the caller is the OUSD Vault.\\n */\\n modifier onlyVault() {\\n require(vaultAddr == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @dev Set address of Uniswap for performing liquidation of strategy reward\\n * tokens. Setting to 0x0 will pause swaps.\\n * @param _address Address of Uniswap\\n */\\n function setUniswapAddr(address _address) external onlyGovernor {\\n uniswapAddr = _address;\\n // Give Uniswap unlimited OUSD allowance\\n ousd.safeApprove(uniswapAddr, 0);\\n ousd.safeApprove(uniswapAddr, uint256(-1));\\n emit UniswapUpdated(_address);\\n }\\n\\n /**\\n * @dev Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible\\n * protocol (e.g. Sushiswap)\\n **/\\n function swap() external onlyVault {\\n if (uniswapAddr == address(0)) return;\\n\\n uint256 sourceAmount = ousd.balanceOf(address(this));\\n if (sourceAmount < 1000 * 1e18) return;\\n\\n // Uniswap redemption path\\n address[] memory path = new address[](4);\\n path[0] = address(ousd);\\n path[1] = address(usdt);\\n path[2] = IUniswapV2Router(uniswapAddr).WETH();\\n path[3] = address(ogn);\\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\\n sourceAmount,\\n uint256(0),\\n path,\\n address(this),\\n now\\n );\\n }\\n\\n /**\\n * @notice Owner function to withdraw a specific amount of a token\\n */\\n function transferToken(address token, uint256 amount)\\n external\\n onlyGovernor\\n nonReentrant\\n {\\n IERC20(token).safeTransfer(_governor(), amount);\\n }\\n}\\n\",\"keccak256\":\"0x69fcccff4a3b6197eab8d67379270817542de29c783520e9743a167941763dc2\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/uniswap/IUniswapV2Router02.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IUniswapV2Router {\\n function WETH() external pure returns (address);\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address[] calldata path,\\n address to,\\n uint256 deadline\\n ) external returns (uint256[] memory amounts);\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n );\\n}\\n\",\"keccak256\":\"0x33943cfab99996faa745df3c21b95b3ed49783b4c3392e4c71e25f6712af509b\"}},\"version\":1}", + "bytecode": "0x6080604052600080546001600160a01b031916737a250d5630b4cf539739df2c5dacb4c659f2488d17905561003c336001600160e01b0361009216565b61004d6001600160e01b036100a416565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36100b7565b600080516020610efc83398151915255565b600080516020610efc8339815191525490565b610e36806100c66000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80638119c065116100665780638119c065146100fa578063aea173d514610102578063c7af335214610128578063d27567f214610144578063d38bfff41461014c57610093565b80630c340a24146100985780631072cbea146100bc578063128a8b05146100ea5780635d36b190146100f2575b600080fd5b6100a0610172565b604080516001600160a01b039092168252519081900360200190f35b6100e8600480360360408110156100d257600080fd5b506001600160a01b038135169060200135610181565b005b6100a0610270565b6100e861027f565b6100e86102e1565b6100e86004803603602081101561011857600080fd5b50356001600160a01b03166106dc565b6101306107e9565b604080519115158252519081900360200190f35b6100a061080c565b6100e86004803603602081101561016257600080fd5b50356001600160a01b0316610824565b600061017c6108cd565b905090565b6101896107e9565b6101d7576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac453580546002811415610241576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556102676102506108cd565b6001600160a01b038616908563ffffffff6108f216565b50600190555050565b6000546001600160a01b031681565b610287610949565b6001600160a01b0316336001600160a01b0316146102d65760405162461bcd60e51b8152600401808060200182810382526030815260200180610dd26030913960400191505060405180910390fd5b6102df3361096e565b565b73e75d77b1865ae93c7eaa3040b038d7aa7bc02f703314610349576040805162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865205661756c74000000000000000000604482015290519081900360640190fd5b6000546001600160a01b031661035e576102df565b604080516370a0823160e01b81523060048201529051600091732a8e1e676ec238d8a992307b495b45b3feaa5e86916370a0823191602480820192602092909190829003018186803b1580156103b357600080fd5b505afa1580156103c7573d6000803e3d6000fd5b505050506040513d60208110156103dd57600080fd5b50519050683635c9adc5dea000008110156103f857506102df565b60408051600480825260a0820190925260609160208201608080388339019050509050732a8e1e676ec238d8a992307b495b45b3feaa5e868160008151811061043d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073dac17f958d2ee523a2206206994597c13d831ec78160018151811061047f57fe5b6001600160a01b03928316602091820292909201810191909152600054604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b1580156104d357600080fd5b505afa1580156104e7573d6000803e3d6000fd5b505050506040513d60208110156104fd57600080fd5b505181518290600290811061050e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050738207c1ffc5b6804f6024322ccf34f29c3541ae268160038151811061055057fe5b6001600160a01b03928316602091820292909201810191909152600080546040516338ed173960e01b815260048101878152602482018490523060648301819052426084840181905260a060448501908152895160a4860152895195909816976338ed1739978b97968b969495939460c4019187810191028083838b5b838110156105e55781810151838201526020016105cd565b505050509050019650505050505050600060405180830381600087803b15801561060e57600080fd5b505af1158015610622573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561064b57600080fd5b810190808051604051939291908464010000000082111561066b57600080fd5b90830190602082018581111561068057600080fd5b825186602082028301116401000000008211171561069d57600080fd5b82525081516020918201928201910280838360005b838110156106ca5781810151838201526020016106b2565b50505050905001604052505050505050565b6106e46107e9565b610732576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038381169190911780835561077692732a8e1e676ec238d8a992307b495b45b3feaa5e86929190911690610a1c565b6000546107aa90732a8e1e676ec238d8a992307b495b45b3feaa5e86906001600160a01b031660001963ffffffff610a1c16565b604080516001600160a01b038316815290517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b60006107f36108cd565b6001600160a01b0316336001600160a01b031614905090565b73e75d77b1865ae93c7eaa3040b038d7aa7bc02f7081565b61082c6107e9565b61087a576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b61088381610b2f565b806001600160a01b03166108956108cd565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610944908490610b53565b505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b0381166109c9576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b03166109db6108cd565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3610a1981610d11565b50565b801580610aa2575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015610a7457600080fd5b505afa158015610a88573d6000803e3d6000fd5b505050506040513d6020811015610a9e57600080fd5b5051155b610add5760405162461bcd60e51b8152600401808060200182810382526036815260200180610d9c6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610944908490610b53565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b610b65826001600160a01b0316610d35565b610bb6576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310610bf45780518252601f199092019160209182019101610bd5565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610c56576040519150601f19603f3d011682016040523d82523d6000602084013e610c5b565b606091505b509150915081610cb2576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610d0b57808060200190516020811015610cce57600080fd5b5051610d0b5760405162461bcd60e51b815260040180806020018281038252602a815260200180610d72602a913960400191505060405180910390fd5b50505050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610d6957508115155b94935050505056fe5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a7231582061d39987b8ceb84ad65ba3fbab46e239c29473a490e71cd6afb189eb9d46dbda64736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c80638119c065116100665780638119c065146100fa578063aea173d514610102578063c7af335214610128578063d27567f214610144578063d38bfff41461014c57610093565b80630c340a24146100985780631072cbea146100bc578063128a8b05146100ea5780635d36b190146100f2575b600080fd5b6100a0610172565b604080516001600160a01b039092168252519081900360200190f35b6100e8600480360360408110156100d257600080fd5b506001600160a01b038135169060200135610181565b005b6100a0610270565b6100e861027f565b6100e86102e1565b6100e86004803603602081101561011857600080fd5b50356001600160a01b03166106dc565b6101306107e9565b604080519115158252519081900360200190f35b6100a061080c565b6100e86004803603602081101561016257600080fd5b50356001600160a01b0316610824565b600061017c6108cd565b905090565b6101896107e9565b6101d7576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac453580546002811415610241576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556102676102506108cd565b6001600160a01b038616908563ffffffff6108f216565b50600190555050565b6000546001600160a01b031681565b610287610949565b6001600160a01b0316336001600160a01b0316146102d65760405162461bcd60e51b8152600401808060200182810382526030815260200180610dd26030913960400191505060405180910390fd5b6102df3361096e565b565b73e75d77b1865ae93c7eaa3040b038d7aa7bc02f703314610349576040805162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865205661756c74000000000000000000604482015290519081900360640190fd5b6000546001600160a01b031661035e576102df565b604080516370a0823160e01b81523060048201529051600091732a8e1e676ec238d8a992307b495b45b3feaa5e86916370a0823191602480820192602092909190829003018186803b1580156103b357600080fd5b505afa1580156103c7573d6000803e3d6000fd5b505050506040513d60208110156103dd57600080fd5b50519050683635c9adc5dea000008110156103f857506102df565b60408051600480825260a0820190925260609160208201608080388339019050509050732a8e1e676ec238d8a992307b495b45b3feaa5e868160008151811061043d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073dac17f958d2ee523a2206206994597c13d831ec78160018151811061047f57fe5b6001600160a01b03928316602091820292909201810191909152600054604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b1580156104d357600080fd5b505afa1580156104e7573d6000803e3d6000fd5b505050506040513d60208110156104fd57600080fd5b505181518290600290811061050e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050738207c1ffc5b6804f6024322ccf34f29c3541ae268160038151811061055057fe5b6001600160a01b03928316602091820292909201810191909152600080546040516338ed173960e01b815260048101878152602482018490523060648301819052426084840181905260a060448501908152895160a4860152895195909816976338ed1739978b97968b969495939460c4019187810191028083838b5b838110156105e55781810151838201526020016105cd565b505050509050019650505050505050600060405180830381600087803b15801561060e57600080fd5b505af1158015610622573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561064b57600080fd5b810190808051604051939291908464010000000082111561066b57600080fd5b90830190602082018581111561068057600080fd5b825186602082028301116401000000008211171561069d57600080fd5b82525081516020918201928201910280838360005b838110156106ca5781810151838201526020016106b2565b50505050905001604052505050505050565b6106e46107e9565b610732576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038381169190911780835561077692732a8e1e676ec238d8a992307b495b45b3feaa5e86929190911690610a1c565b6000546107aa90732a8e1e676ec238d8a992307b495b45b3feaa5e86906001600160a01b031660001963ffffffff610a1c16565b604080516001600160a01b038316815290517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b60006107f36108cd565b6001600160a01b0316336001600160a01b031614905090565b73e75d77b1865ae93c7eaa3040b038d7aa7bc02f7081565b61082c6107e9565b61087a576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b61088381610b2f565b806001600160a01b03166108956108cd565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610944908490610b53565b505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b0381166109c9576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b03166109db6108cd565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3610a1981610d11565b50565b801580610aa2575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015610a7457600080fd5b505afa158015610a88573d6000803e3d6000fd5b505050506040513d6020811015610a9e57600080fd5b5051155b610add5760405162461bcd60e51b8152600401808060200182810382526036815260200180610d9c6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610944908490610b53565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b610b65826001600160a01b0316610d35565b610bb6576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310610bf45780518252601f199092019160209182019101610bd5565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610c56576040519150601f19603f3d011682016040523d82523d6000602084013e610c5b565b606091505b509150915081610cb2576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610d0b57808060200190516020811015610cce57600080fd5b5051610d0b5760405162461bcd60e51b815260040180806020018281038252602a815260200180610d72602a913960400191505060405180910390fd5b50505050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610d6957508115155b94935050505056fe5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a7231582061d39987b8ceb84ad65ba3fbab46e239c29473a490e71cd6afb189eb9d46dbda64736f6c634300050b0032", + "devdoc": { + "methods": { + "claimGovernance()": { + "details": "Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor." + }, + "governor()": { + "details": "Returns the address of the current Governor." + }, + "isGovernor()": { + "details": "Returns true if the caller is the current Governor." + }, + "setUniswapAddr(address)": { + "details": "Set address of Uniswap for performing liquidation of strategy reward tokens. Setting to 0x0 will pause swaps.", + "params": { + "_address": "Address of Uniswap" + } + }, + "swap()": { + "details": "Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible protocol (e.g. Sushiswap)*" + }, + "transferGovernance(address)": { + "details": "Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete", + "params": { + "_newGovernor": "Address of the new Governor" + } + } + } + }, + "userdoc": { + "methods": { + "transferToken(address,uint256)": { + "notice": "Owner function to withdraw a specific amount of a token" + } + } + } +} \ No newline at end of file diff --git a/contracts/deployments/mainnet/OracleRouter.json b/contracts/deployments/mainnet/OracleRouter.json new file mode 100644 index 0000000000..222cce24c8 --- /dev/null +++ b/contracts/deployments/mainnet/OracleRouter.json @@ -0,0 +1,64 @@ +{ + "address": "0xBAe5888057Fb3be601Fb172873596DaE7EB701A8", + "abi": [ + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "price", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xb71fa4e0b278b5d9de47768ef1ed168d8d5203a368b49ab38dbb79840f07c29d", + "receipt": { + "to": null, + "from": "0x71F78361537A6f7B6818e7A760c8bC0146D93f50", + "contractAddress": "0xBAe5888057Fb3be601Fb172873596DaE7EB701A8", + "transactionIndex": 145, + "gasUsed": "236798", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa669ae1a8555751ec6aaa0ffedc78019f061ea8fdecbc8bdf638f9a5508a5260", + "transactionHash": "0xb71fa4e0b278b5d9de47768ef1ed168d8d5203a368b49ab38dbb79840f07c29d", + "logs": [], + "blockNumber": 12104663, + "cumulativeGasUsed": "6318221", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "cca309778b0bcb384ba7e2e97bde53a0", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"price\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"price(address)\":{\"params\":{\"asset\":\"address of the asset\"},\"return\":\"uint256 USD price of 1 of the asset, in 8 decimal fixed\"}}},\"userdoc\":{\"methods\":{\"price(address)\":{\"notice\":\"Returns the total price in 8 digit USD for a given asset.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/oracle/OracleRouter.sol\":\"OracleRouter\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IOracle {\\n /**\\n * @dev returns the asset price in USD, 8 decimal digits.\\n */\\n function price(address asset) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x7ddbe1f9ed76feb2fbd52ecfe449e17ef67f7edd5616c6a1eda92a84baa1190f\"},\"contracts/interfaces/chainlink/AggregatorV3Interface.sol\":{\"content\":\"pragma solidity ^0.5.11;\\n\\ninterface AggregatorV3Interface {\\n function decimals() external view returns (uint8);\\n\\n function description() external view returns (string memory);\\n\\n function version() external view returns (uint256);\\n\\n // getRoundData and latestRoundData should both raise \\\"No data present\\\"\\n // if they do not have data to report, instead of returning unset values\\n // which could be misinterpreted as actual reported values.\\n function getRoundData(uint80 _roundId)\\n external\\n view\\n returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n\\n function latestRoundData()\\n external\\n view\\n returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n}\\n\",\"keccak256\":\"0xef73b8afeb1cf9a35e7f5d9cbc878eff44841f7a78a56a0aaafe9943c32848f7\"},\"contracts/oracle/OracleRouter.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport \\\"../interfaces/chainlink/AggregatorV3Interface.sol\\\";\\nimport { IOracle } from \\\"../interfaces/IOracle.sol\\\";\\n\\ncontract OracleRouterBase is IOracle {\\n uint256 constant MIN_DRIFT = uint256(70000000);\\n uint256 constant MAX_DRIFT = uint256(130000000);\\n\\n /**\\n * @dev The price feed contract to use for a particular asset.\\n * @param asset address of the asset\\n */\\n function feed(address asset) internal view returns (address);\\n\\n /**\\n * @notice Returns the total price in 8 digit USD for a given asset.\\n * @param asset address of the asset\\n * @return uint256 USD price of 1 of the asset, in 8 decimal fixed\\n */\\n function price(address asset) external view returns (uint256) {\\n address _feed = feed(asset);\\n require(_feed != address(0), \\\"Asset not available\\\");\\n (\\n uint80 roundID,\\n int256 _iprice,\\n uint256 startedAt,\\n uint256 timeStamp,\\n uint80 answeredInRound\\n ) = AggregatorV3Interface(_feed).latestRoundData();\\n uint256 _price = uint256(_iprice);\\n require(_price <= MAX_DRIFT, \\\"Oracle: Price exceeds max\\\");\\n require(_price >= MIN_DRIFT, \\\"Oracle: Price under min\\\");\\n return uint256(_price);\\n }\\n}\\n\\ncontract OracleRouter is OracleRouterBase {\\n /**\\n * @dev The price feed contract to use for a particular asset.\\n * @param asset address of the asset\\n */\\n function feed(address asset) internal view returns (address) {\\n // DAI\\n if (asset == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) {\\n return address(0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9);\\n // USDC\\n } else if (\\n asset == address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)\\n ) {\\n return address(0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6);\\n // USDT\\n } else if (\\n asset == address(0xdAC17F958D2ee523a2206206994597C13D831ec7)\\n ) {\\n return address(0x3E7d1eAB13ad0104d2750B8863b489D65364e32D);\\n } else {\\n require(false, \\\"Asset not available\\\");\\n }\\n }\\n}\\n\\ncontract OracleRouterDev is OracleRouterBase {\\n mapping(address => address) public assetToFeed;\\n\\n function setFeed(address _asset, address _feed) external {\\n assetToFeed[_asset] = _feed;\\n }\\n\\n /**\\n * @dev The price feed contract to use for a particular asset.\\n * @param asset address of the asset\\n */\\n function feed(address asset) internal view returns (address) {\\n return assetToFeed[asset];\\n }\\n}\\n\",\"keccak256\":\"0xfb59c9ffec329bad84bb4e7d56b8688472afa4523ec4f93bce3033314a2694ff\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610352806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063aea9107814610030575b600080fd5b6100566004803603602081101561004657600080fd5b50356001600160a01b0316610068565b60408051918252519081900360200190f35b60008061007483610218565b90506001600160a01b0381166100c7576040805162461bcd60e51b81526020600482015260136024820152724173736574206e6f7420617661696c61626c6560681b604482015290519081900360640190fd5b6000806000806000856001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561010857600080fd5b505afa15801561011c573d6000803e3d6000fd5b505050506040513d60a081101561013257600080fd5b50805160208201516040830151606084015160809094015192985090965094509092509050836307bfa4808111156101b1576040805162461bcd60e51b815260206004820152601960248201527f4f7261636c653a2050726963652065786365656473206d617800000000000000604482015290519081900360640190fd5b63042c1d8081101561020a576040805162461bcd60e51b815260206004820152601760248201527f4f7261636c653a20507269636520756e646572206d696e000000000000000000604482015290519081900360640190fd5b96505050505050505b919050565b60006001600160a01b038216736b175474e89094c44da98b954eedeac495271d0f141561025a575073aed0c38402a5d19df6e4c03f4e2dced6e29c1ee9610213565b6001600160a01b03821673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48141561029a5750738fffffd4afb6115b954bd326cbe7b4ba576818f6610213565b6001600160a01b03821673dac17f958d2ee523a2206206994597c13d831ec714156102da5750733e7d1eab13ad0104d2750b8863b489d65364e32d610213565b6040805162461bcd60e51b81526020600482015260136024820152724173736574206e6f7420617661696c61626c6560681b604482015290519081900360640190fdfea265627a7a723158205a0faac8e8f1032354adde1b81703c6f8f40f7764602d0c554c7ca614fb302ca64736f6c634300050b0032", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063aea9107814610030575b600080fd5b6100566004803603602081101561004657600080fd5b50356001600160a01b0316610068565b60408051918252519081900360200190f35b60008061007483610218565b90506001600160a01b0381166100c7576040805162461bcd60e51b81526020600482015260136024820152724173736574206e6f7420617661696c61626c6560681b604482015290519081900360640190fd5b6000806000806000856001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561010857600080fd5b505afa15801561011c573d6000803e3d6000fd5b505050506040513d60a081101561013257600080fd5b50805160208201516040830151606084015160809094015192985090965094509092509050836307bfa4808111156101b1576040805162461bcd60e51b815260206004820152601960248201527f4f7261636c653a2050726963652065786365656473206d617800000000000000604482015290519081900360640190fd5b63042c1d8081101561020a576040805162461bcd60e51b815260206004820152601760248201527f4f7261636c653a20507269636520756e646572206d696e000000000000000000604482015290519081900360640190fd5b96505050505050505b919050565b60006001600160a01b038216736b175474e89094c44da98b954eedeac495271d0f141561025a575073aed0c38402a5d19df6e4c03f4e2dced6e29c1ee9610213565b6001600160a01b03821673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48141561029a5750738fffffd4afb6115b954bd326cbe7b4ba576818f6610213565b6001600160a01b03821673dac17f958d2ee523a2206206994597c13d831ec714156102da5750733e7d1eab13ad0104d2750b8863b489d65364e32d610213565b6040805162461bcd60e51b81526020600482015260136024820152724173736574206e6f7420617661696c61626c6560681b604482015290519081900360640190fdfea265627a7a723158205a0faac8e8f1032354adde1b81703c6f8f40f7764602d0c554c7ca614fb302ca64736f6c634300050b0032", + "devdoc": { + "methods": { + "price(address)": { + "params": { + "asset": "address of the asset" + }, + "return": "uint256 USD price of 1 of the asset, in 8 decimal fixed" + } + } + }, + "userdoc": { + "methods": { + "price(address)": { + "notice": "Returns the total price in 8 digit USD for a given asset." + } + } + } +} \ No newline at end of file diff --git a/contracts/deployments/mainnet/VaultAdmin.json b/contracts/deployments/mainnet/VaultAdmin.json index 79546dd6a0..09d1e5d14f 100644 --- a/contracts/deployments/mainnet/VaultAdmin.json +++ b/contracts/deployments/mainnet/VaultAdmin.json @@ -1,5 +1,5 @@ { - "address": "0xb5f7E47Bc7D271b3df4824BDcFBB279a719F8Ae6", + "address": "0x8E55b527901BC88206a1cE5C292B2404bcb8F76D", "abi": [ { "constant": false, @@ -96,6 +96,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDMint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -156,27 +177,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDRedeem", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": false, "inputs": [ @@ -317,8 +317,14 @@ }, { "constant": false, - "inputs": [], - "name": "claimGovernance", + "inputs": [ + { + "internalType": "address", + "name": "_strategyAddr", + "type": "address" + } + ], + "name": "withdrawAllFromStrategy", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -326,38 +332,26 @@ }, { "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_maxSupplyDiff", - "type": "uint256" - } - ], - "name": "setMaxSupplyDiff", + "inputs": [], + "name": "claimGovernance", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDMint", - "outputs": [ { "internalType": "uint256", - "name": "", + "name": "_maxSupplyDiff", "type": "uint256" } ], + "name": "setMaxSupplyDiff", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -405,6 +399,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -584,6 +599,15 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [], + "name": "withdrawAllFromStrategies", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -958,42 +982,42 @@ "type": "event" } ], - "transactionHash": "0xb6537b135038ec057a1e8a278ce4f289ce187550e5a751431794cb5fc8b96033", + "transactionHash": "0x3631b214cb20ed5e915fb93a93b3b12158c481f1c8f8fb1c3ab2f6e006b15b7b", "receipt": { "to": null, "from": "0x71F78361537A6f7B6818e7A760c8bC0146D93f50", - "contractAddress": "0xb5f7E47Bc7D271b3df4824BDcFBB279a719F8Ae6", - "transactionIndex": 93, - "gasUsed": "2698492", - "logsBloom": "0x00000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800010004000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb95512fa8985d75b68ea1966bcbd4969f63307ba5dba97dc8b0887403194b2d7", - "transactionHash": "0xb6537b135038ec057a1e8a278ce4f289ce187550e5a751431794cb5fc8b96033", + "contractAddress": "0x8E55b527901BC88206a1cE5C292B2404bcb8F76D", + "transactionIndex": 162, + "gasUsed": "2795497", + "logsBloom": "0x00000000000000004000000000000000000000000000001000000000000008000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000001000000200000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x680e5bbb7bbabb9118ecbe602aae8011d9bfafeb609f27d054b56048ad0339eb", + "transactionHash": "0x3631b214cb20ed5e915fb93a93b3b12158c481f1c8f8fb1c3ab2f6e006b15b7b", "logs": [ { - "transactionIndex": 93, - "blockNumber": 11831731, - "transactionHash": "0xb6537b135038ec057a1e8a278ce4f289ce187550e5a751431794cb5fc8b96033", - "address": "0xb5f7E47Bc7D271b3df4824BDcFBB279a719F8Ae6", + "transactionIndex": 162, + "blockNumber": 12104653, + "transactionHash": "0x3631b214cb20ed5e915fb93a93b3b12158c481f1c8f8fb1c3ab2f6e006b15b7b", + "address": "0x8E55b527901BC88206a1cE5C292B2404bcb8F76D", "topics": [ "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x00000000000000000000000071f78361537a6f7b6818e7a760c8bc0146d93f50" ], "data": "0x", - "logIndex": 74, - "blockHash": "0xb95512fa8985d75b68ea1966bcbd4969f63307ba5dba97dc8b0887403194b2d7" + "logIndex": 124, + "blockHash": "0x680e5bbb7bbabb9118ecbe602aae8011d9bfafeb609f27d054b56048ad0339eb" } ], - "blockNumber": 11831731, - "cumulativeGasUsed": "6537016", + "blockNumber": 12104653, + "cumulativeGasUsed": "10595294", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "9fed08ce0928345e8230635be8b09173", - "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":false,\"inputs\":[],\"name\":\"unpauseRebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"redeemFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"setTrusteeFeeBps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyAddr\",\"type\":\"address\"}],\"name\":\"harvest\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"transferToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"removeStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultBuffer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"}],\"name\":\"priceUSDRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setTrusteeAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"setPriceProvider\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"approveStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pauseCapital\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"harvest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"supportAsset\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebaseThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"setMaxSupplyDiff\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"}],\"name\":\"priceUSDMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setStrategistAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyFromAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategyToAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_assets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"}],\"name\":\"reallocate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxSupplyDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"setVaultBuffer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpauseCapital\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoAllocateThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetDefaultStrategies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setUniswapAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"setAutoAllocateThreshold\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"priceProvider\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"setRebaseThreshold\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"setAssetDefaultStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pauseRebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"capitalPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"setRedeemFeeBps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImpl\",\"type\":\"address\"}],\"name\":\"setAdminImpl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"AssetSupported\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"AssetDefaultStrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebasePaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebaseUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"VaultBufferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"RedeemFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"PriceProviderUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"AllocateThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"RebaseThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyDiffChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_yield\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"YieldDistribution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"TrusteeFeeBpsChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"TrusteeAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"approveStrategy(address)\":{\"details\":\"Add a strategy to the Vault.\",\"params\":{\"_addr\":\"Address of the strategy to add\"}},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"harvest()\":{\"details\":\"Collect reward tokens from all strategies and swap for supported stablecoin via Uniswap\"},\"harvest(address)\":{\"details\":\"Collect reward tokens for a specific strategy and swap for supported stablecoin via Uniswap. Called from the vault.\",\"params\":{\"_strategyAddr\":\"Address of the strategy to collect rewards from\"}},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"pauseCapital()\":{\"details\":\"Set the deposit paused flag to true to prevent capital movement.\"},\"pauseRebase()\":{\"details\":\"Set the deposit paused flag to true to prevent rebasing.\"},\"priceUSDMint(string)\":{\"details\":\"Returns the total price in 18 digit USD for a given asset. Using Min since min is what we use for mint pricing\",\"params\":{\"symbol\":\"String symbol of the asset\"},\"return\":\"uint256 USD price of 1 of the asset\"},\"priceUSDRedeem(string)\":{\"details\":\"Returns the total price in 18 digit USD for a given asset. Using Max since max is what we use for redeem pricing\",\"params\":{\"symbol\":\"String symbol of the asset\"},\"return\":\"uint256 USD price of 1 of the asset\"},\"reallocate(address,address,address[],uint256[])\":{\"params\":{\"_amounts\":\"Array of amounts of each corresponding asset to move.\",\"_assets\":\"Array of asset address that will be moved\",\"_strategyFromAddress\":\"Address of Strategy to move assets from.\",\"_strategyToAddress\":\"Address of Strategy to move assets to.\"}},\"removeStrategy(address)\":{\"details\":\"Remove a strategy from the Vault. Removes all invested assets and returns them to the Vault.\",\"params\":{\"_addr\":\"Address of the strategy to remove\"}},\"setAdminImpl(address)\":{\"details\":\"set the implementation for the admin, this needs to be in a base class else we cannot set it\",\"params\":{\"newImpl\":\"address of the implementation\"}},\"setAssetDefaultStrategy(address,address)\":{\"details\":\"Set the default Strategy for an asset, i.e. the one which the asset will be automatically allocated to and withdrawn from\",\"params\":{\"_asset\":\"Address of the asset\",\"_strategy\":\"Address of the Strategy\"}},\"setAutoAllocateThreshold(uint256)\":{\"details\":\"Sets the minimum amount of OUSD in a mint to trigger an automatic allocation of funds afterwords.\",\"params\":{\"_threshold\":\"OUSD amount with 18 fixed decimals.\"}},\"setMaxSupplyDiff(uint256)\":{\"details\":\"Sets the maximum allowable difference between total supply and backing assets' value.\"},\"setPriceProvider(address)\":{\"details\":\"Set address of price provider.\",\"params\":{\"_priceProvider\":\"Address of price provider\"}},\"setRebaseThreshold(uint256)\":{\"details\":\"Set a minimum amount of OUSD in a mint or redeem that triggers a rebase\",\"params\":{\"_threshold\":\"OUSD amount with 18 fixed decimals.\"}},\"setRedeemFeeBps(uint256)\":{\"details\":\"Set a fee in basis points to be charged for a redeem.\",\"params\":{\"_redeemFeeBps\":\"Basis point fee to be charged\"}},\"setStrategistAddr(address)\":{\"details\":\"Set address of Strategist\",\"params\":{\"_address\":\"Address of Strategist\"}},\"setTrusteeAddress(address)\":{\"details\":\"Sets the trusteeAddress that can receive a portion of yield. Setting to the zero address disables this feature.\"},\"setTrusteeFeeBps(uint256)\":{\"details\":\"Sets the TrusteeFeeBps to the percentage of yield that should be received in basis points.\"},\"setUniswapAddr(address)\":{\"details\":\"Set address of Uniswap for performing liquidation of strategy reward tokens\",\"params\":{\"_address\":\"Address of Uniswap\"}},\"setVaultBuffer(uint256)\":{\"details\":\"Set a buffer of assets to keep in the Vault to handle most redemptions without needing to spend gas unwinding assets from a Strategy.\",\"params\":{\"_vaultBuffer\":\"Percentage using 18 decimals. 100% = 1e18.\"}},\"supportAsset(address)\":{\"details\":\"Add a supported asset to the contract, i.e. one that can be to mint OUSD.\",\"params\":{\"_asset\":\"Address of asset\"}},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}},\"transferToken(address,uint256)\":{\"details\":\"Transfer token to governor. Intended for recovering tokens stuck in contract, i.e. mistaken sends.\",\"params\":{\"_amount\":\"Amount of the asset to transfer\",\"_asset\":\"Address for the asset\"}},\"unpauseCapital()\":{\"details\":\"Set the deposit paused flag to false to enable capital movement.\"},\"unpauseRebase()\":{\"details\":\"Set the deposit paused flag to true to allow rebasing.\"}}},\"userdoc\":{\"methods\":{\"reallocate(address,address,address[],uint256[])\":{\"notice\":\"Move assets from one Strategy to another\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/vault/VaultAdmin.sol\":\"VaultAdmin\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"@openzeppelin/upgrades/contracts/Initializable.sol\":{\"content\":\"pragma solidity >=0.4.24 <0.7.0;\\n\\n\\n/**\\n * @title Initializable\\n *\\n * @dev Helper contract to support initializer functions. To use it, replace\\n * the constructor with a function that has the `initializer` modifier.\\n * WARNING: Unlike constructors, initializer functions must be manually\\n * invoked. This applies both to deploying an Initializable contract, as well\\n * as extending an Initializable contract via inheritance.\\n * WARNING: When used with inheritance, manual care must be taken to not invoke\\n * a parent initializer twice, or ensure that all initializers are idempotent,\\n * because this is not dealt with automatically as with constructors.\\n */\\ncontract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to use in the initializer function of a contract.\\n */\\n modifier initializer() {\\n require(initializing || isConstructor() || !initialized, \\\"Contract instance has already been initialized\\\");\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function isConstructor() private view returns (bool) {\\n // extcodesize checks the size of the code stored in an address, and\\n // address returns the current address. Since the code is still not\\n // deployed when running a constructor, any checks on its code size will\\n // yield zero, making it an effective way to detect if a contract is\\n // under construction or not.\\n address self = address(this);\\n uint256 cs;\\n assembly { cs := extcodesize(self) }\\n return cs == 0;\\n }\\n\\n // Reserved storage space to allow for layout changes in the future.\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x9bfec92e36234ecc99b5d37230acb6cd1f99560233753162204104a4897e8721\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x01eab42b6d54fa5389598e0663c24680ecc017e2da848e8ea1c40aeaa8225eef\"},\"contracts/interfaces/IMinMaxOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IMinMaxOracle {\\n //Assuming 8 decimals\\n function priceMin(string calldata symbol) external view returns (uint256);\\n\\n function priceMax(string calldata symbol) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x164c8759ca5a8e39bbe1de6b2504098c543b2f15663c9d452e083418f8313f48\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to platform\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Deposit the entire balance of all supported assets in the Strategy\\n * to the platform\\n */\\n function depositAll() external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardToken() external;\\n\\n /**\\n * @dev The address of the reward token for the Strategy.\\n */\\n function rewardTokenAddress() external pure returns (address);\\n\\n /**\\n * @dev The threshold (denominated in the reward token) over which the\\n * vault will auto harvest on allocate calls.\\n */\\n function rewardLiquidationThreshold() external pure returns (uint256);\\n}\\n\",\"keccak256\":\"0xe03dc1c97ad3677296da9a7e1e5f708abd227d1147f6f220c5cc8f23c1cd87e0\"},\"contracts/interfaces/uniswap/IUniswapV2Router02.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IUniswapV2Router {\\n function WETH() external pure returns (address);\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address[] calldata path,\\n address to,\\n uint256 deadline\\n ) external returns (uint256[] memory amounts);\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n );\\n}\\n\",\"keccak256\":\"0x33943cfab99996faa745df3c21b95b3ed49783b4c3392e4c71e25f6712af509b\"},\"contracts/token/OUSD.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {\\n InitializableERC20Detailed\\n} from \\\"../utils/InitializableERC20Detailed.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\n/**\\n * NOTE that this is an ERC20 token but the invariant that the sum of\\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\\n * rebasing design. Any integrations with OUSD should be aware.\\n */\\n\\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n\\n event TotalSupplyUpdated(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n\\n enum RebaseOptions { NotSet, OptOut, OptIn }\\n\\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\\n uint256 public _totalSupply;\\n mapping(address => mapping(address => uint256)) private _allowances;\\n address public vaultAddress = address(0);\\n mapping(address => uint256) private _creditBalances;\\n uint256 public rebasingCredits;\\n uint256 public rebasingCreditsPerToken;\\n // Frozen address/credits are non rebasing (value is held in contracts which\\n // do not receive yield unless they explicitly opt in)\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) public nonRebasingCreditsPerToken;\\n mapping(address => RebaseOptions) public rebaseState;\\n\\n function initialize(\\n string calldata _nameArg,\\n string calldata _symbolArg,\\n address _vaultAddress\\n ) external onlyGovernor initializer {\\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\\n rebasingCreditsPerToken = 1e18;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Savings Manager contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return The total supply of OUSD.\\n */\\n function totalSupply() public view returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the _amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n if (_creditBalances[_account] == 0) return 0;\\n return\\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n return (_creditBalances[_account], _creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the _amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(\\n _value <= balanceOf(msg.sender),\\n \\\"Transfer greater than balance\\\"\\n );\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The _amount of tokens to be transferred.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(_value <= balanceOf(_from), \\\"Transfer greater than balance\\\");\\n\\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\\n _value\\n );\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Update the count of non rebasing credits in response to a transfer\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value Amount of OUSD to transfer\\n */\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\\n\\n // Credits deducted and credited might be different due to the\\n // differing creditsPerToken used by each account\\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\\n\\n _creditBalances[_from] = _creditBalances[_from].sub(\\n creditsDeducted,\\n \\\"Transfer amount exceeds balance\\\"\\n );\\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\\n\\n if (isNonRebasingTo && !isNonRebasingFrom) {\\n // Transfer to non-rebasing account from rebasing account, credits\\n // are removed from the non rebasing tally\\n nonRebasingSupply = nonRebasingSupply.add(_value);\\n // Update rebasingCredits by subtracting the deducted amount\\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\\n // Transfer to rebasing account from non-rebasing account\\n // Decreasing non-rebasing credits by the amount that was sent\\n nonRebasingSupply = nonRebasingSupply.sub(_value);\\n // Update rebasingCredits by adding the credited amount\\n rebasingCredits = rebasingCredits.add(creditsCredited);\\n }\\n }\\n\\n /**\\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n public\\n view\\n returns (uint256)\\n {\\n return _allowances[_owner][_spender];\\n }\\n\\n /**\\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\\n * msg.sender. This method is included for ERC20 compatibility.\\n * increaseAllowance and decreaseAllowance should be used instead.\\n * Changing an allowance with this method brings the risk that someone may transfer both\\n * the old and the new allowance - if they are both greater than zero - if a transfer\\n * transaction is mined before the later approve() call is mined.\\n *\\n * @param _spender The address which will spend the funds.\\n * @param _value The _amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) public returns (bool) {\\n _allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\\n * This method should be used instead of approve() to avoid the double approval vulnerability\\n * described above.\\n * @param _spender The address which will spend the funds.\\n * @param _addedValue The _amount of tokens to increase the allowance by.\\n */\\n function increaseAllowance(address _spender, uint256 _addedValue)\\n public\\n returns (bool)\\n {\\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\\n .add(_addedValue);\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\\n * @param _spender The address which will spend the funds.\\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\\n */\\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\\n public\\n returns (bool)\\n {\\n uint256 oldValue = _allowances[msg.sender][_spender];\\n if (_subtractedValue >= oldValue) {\\n _allowances[msg.sender][_spender] = 0;\\n } else {\\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\\n }\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Mints new tokens, increasing totalSupply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n _mint(_account, _amount);\\n }\\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 * - `to` cannot be the zero address.\\n */\\n function _mint(address _account, uint256 _amount) internal nonReentrant {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\\n\\n // If the account is non rebasing and doesn't have a set creditsPerToken\\n // then set it i.e. this is a mint from a fresh contract\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.add(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.add(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.add(_amount);\\n\\n require(_totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @dev Burns tokens, decreasing totalSupply.\\n */\\n function burn(address account, uint256 amount) external onlyVault {\\n _burn(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 nonReentrant {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n uint256 currentCredits = _creditBalances[_account];\\n\\n // Remove the credits, burning rounding errors\\n if (\\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\\n ) {\\n // Handle dust from rounding\\n _creditBalances[_account] = 0;\\n } else if (currentCredits > creditAmount) {\\n _creditBalances[_account] = _creditBalances[_account].sub(\\n creditAmount\\n );\\n } else {\\n revert(\\\"Remove exceeds balance\\\");\\n }\\n\\n // Remove from the credit tallies and non-rebasing supply\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.sub(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.sub(_amount);\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n if (nonRebasingCreditsPerToken[_account] != 0) {\\n return nonRebasingCreditsPerToken[_account];\\n } else {\\n return rebasingCreditsPerToken;\\n }\\n }\\n\\n /**\\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\\n * Also, ensure contracts are non-rebasing if they have not opted in.\\n * @param _account Address of the account.\\n */\\n function _isNonRebasingAccount(address _account) internal returns (bool) {\\n bool isContract = Address.isContract(_account);\\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\\n _ensureRebasingMigration(_account);\\n }\\n return nonRebasingCreditsPerToken[_account] > 0;\\n }\\n\\n /**\\n * @dev Ensures internal account for rebasing and non-rebasing credits and\\n * supply is updated following deployment of frozen yield change.\\n */\\n function _ensureRebasingMigration(address _account) internal {\\n if (nonRebasingCreditsPerToken[_account] == 0) {\\n // Set fixed credits per token for this account\\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\\n // Update non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\\n // Update credit tallies\\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\\n }\\n }\\n\\n /**\\n * @dev Add a contract address to the non rebasing exception list. I.e. the\\n * address's balance will be part of rebases so the account will be exposed\\n * to upside and downside.\\n */\\n function rebaseOptIn() public nonReentrant {\\n require(_isNonRebasingAccount(msg.sender), \\\"Account has not opted out\\\");\\n\\n // Convert balance into the same amount at the current exchange rate\\n uint256 newCreditBalance = _creditBalances[msg.sender]\\n .mul(rebasingCreditsPerToken)\\n .div(_creditsPerToken(msg.sender));\\n\\n // Decreasing non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\\n\\n _creditBalances[msg.sender] = newCreditBalance;\\n\\n // Increase rebasing credits, totalSupply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\\n\\n rebaseState[msg.sender] = RebaseOptions.OptIn;\\n\\n // Delete any fixed credits per token\\n delete nonRebasingCreditsPerToken[msg.sender];\\n }\\n\\n /**\\n * @dev Remove a contract address to the non rebasing exception list.\\n */\\n function rebaseOptOut() public nonReentrant {\\n require(!_isNonRebasingAccount(msg.sender), \\\"Account has not opted in\\\");\\n\\n // Increase non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\\n // Set fixed credits per token\\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\\n\\n // Decrease rebasing credits, total supply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\\n\\n // Mark explicitly opted out of rebasing\\n rebaseState[msg.sender] = RebaseOptions.OptOut;\\n }\\n\\n /**\\n * @dev Modify the supply without minting new tokens. This uses a change in\\n * the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n * @return uint256 representing the new total supply.\\n */\\n function changeSupply(uint256 _newTotalSupply)\\n external\\n onlyVault\\n nonReentrant\\n {\\n require(_totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (_totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n return;\\n }\\n\\n _totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\\n _totalSupply.sub(nonRebasingSupply)\\n );\\n\\n require(rebasingCreditsPerToken > 0, \\\"Invalid change in supply\\\");\\n\\n _totalSupply = rebasingCredits\\n .divPrecisely(rebasingCreditsPerToken)\\n .add(nonRebasingSupply);\\n\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n }\\n}\\n\",\"keccak256\":\"0xea89a8b152b363982ba8db340b1e20c3194b2e75a06630cbbf43e3c50fff61a4\"},\"contracts/utils/Helpers.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0xd2ca92e0af883dc1aec5b22caced274e59829e0e30a9e955dcc48b8d921f5cdc\"},\"contracts/utils/InitializableERC20Detailed.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/**\\n * @dev Optional functions from the ERC20 standard.\\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\\n */\\ncontract InitializableERC20Detailed is IERC20 {\\n // Storage gap to skip storage from prior to OUSD reset\\n uint256[100] private _____gap;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\\n * these values are immutable: they can only be set once during\\n * construction.\\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\\n */\\n function _initialize(\\n string memory nameArg,\\n string memory symbolArg,\\n uint8 decimalsArg\\n ) internal {\\n _name = nameArg;\\n _symbol = symbolArg;\\n _decimals = decimalsArg;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view 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 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.\\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 returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x7919369d0f3bd74b4f0ee78a682afe43f91b186cdd0708e303068e4feeb29007\"},\"contracts/utils/StableMath.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n// Based on StableMath from Stability Labs Pty. Ltd.\\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\\n\\nlibrary StableMath {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Scaling unit for use in specific calculations,\\n * where 1 * 10**18, or 1e18 represents a unit '1'\\n */\\n uint256 private constant FULL_SCALE = 1e18;\\n\\n /***************************************\\n Helpers\\n ****************************************/\\n\\n /**\\n * @dev Adjust the scale of an integer\\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\\n */\\n function scaleBy(uint256 x, int8 adjustment)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (adjustment > 0) {\\n x = x.mul(10**uint256(adjustment));\\n } else if (adjustment < 0) {\\n x = x.div(10**uint256(adjustment * -1));\\n }\\n return x;\\n }\\n\\n /***************************************\\n Precise Arithmetic\\n ****************************************/\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\\n return mulTruncateScale(x, y, FULL_SCALE);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @param scale Scale unit\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncateScale(\\n uint256 x,\\n uint256 y,\\n uint256 scale\\n ) internal pure returns (uint256) {\\n // e.g. assume scale = fullScale\\n // z = 10e18 * 9e17 = 9e36\\n uint256 z = x.mul(y);\\n // return 9e38 / 1e18 = 9e18\\n return z.div(scale);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit, rounded up to the closest base unit.\\n */\\n function mulTruncateCeil(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e17 * 17268172638 = 138145381104e17\\n uint256 scaled = x.mul(y);\\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\\n return ceil.div(FULL_SCALE);\\n }\\n\\n /**\\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\\n * @param x Left hand input to division\\n * @param y Right hand input to division\\n * @return Result after multiplying the left operand by the scale, and\\n * executing the division on the right hand input.\\n */\\n function divPrecisely(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e18 * 1e18 = 8e36\\n uint256 z = x.mul(FULL_SCALE);\\n // e.g. 8e36 / 10e18 = 8e17\\n return z.div(y);\\n }\\n}\\n\",\"keccak256\":\"0xa77fccf850feb6d54ba3a6530f92554caef8a67a1ceb573d4f8a5d1bf64ff9d2\"},\"contracts/vault/VaultAdmin.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Vault Admin Contract\\n * @notice The VaultAdmin contract makes configuration and admin calls on the vault.\\n * @author Origin Protocol Inc\\n */\\n\\nimport \\\"./VaultStorage.sol\\\";\\nimport { IMinMaxOracle } from \\\"../interfaces/IMinMaxOracle.sol\\\";\\nimport { IUniswapV2Router } from \\\"../interfaces/uniswap/IUniswapV2Router02.sol\\\";\\n\\ncontract VaultAdmin is VaultStorage {\\n /**\\n * @dev Verifies that the caller is the Vault, Governor, or Strategist.\\n */\\n modifier onlyVaultOrGovernorOrStrategist() {\\n require(\\n msg.sender == address(this) ||\\n msg.sender == strategistAddr ||\\n isGovernor(),\\n \\\"Caller is not the Vault, Governor, or Strategist\\\"\\n );\\n _;\\n }\\n\\n modifier onlyGovernorOrStrategist() {\\n require(\\n msg.sender == strategistAddr || isGovernor(),\\n \\\"Caller is not the Strategist or Governor\\\"\\n );\\n _;\\n }\\n\\n /***************************************\\n Configuration\\n ****************************************/\\n\\n /**\\n * @dev Set address of price provider.\\n * @param _priceProvider Address of price provider\\n */\\n function setPriceProvider(address _priceProvider) external onlyGovernor {\\n priceProvider = _priceProvider;\\n emit PriceProviderUpdated(_priceProvider);\\n }\\n\\n /**\\n * @dev Set a fee in basis points to be charged for a redeem.\\n * @param _redeemFeeBps Basis point fee to be charged\\n */\\n function setRedeemFeeBps(uint256 _redeemFeeBps) external onlyGovernor {\\n redeemFeeBps = _redeemFeeBps;\\n emit RedeemFeeUpdated(_redeemFeeBps);\\n }\\n\\n /**\\n * @dev Set a buffer of assets to keep in the Vault to handle most\\n * redemptions without needing to spend gas unwinding assets from a Strategy.\\n * @param _vaultBuffer Percentage using 18 decimals. 100% = 1e18.\\n */\\n function setVaultBuffer(uint256 _vaultBuffer) external onlyGovernor {\\n require(_vaultBuffer <= 1e18, \\\"Invalid value\\\");\\n vaultBuffer = _vaultBuffer;\\n emit VaultBufferUpdated(_vaultBuffer);\\n }\\n\\n /**\\n * @dev Sets the minimum amount of OUSD in a mint to trigger an\\n * automatic allocation of funds afterwords.\\n * @param _threshold OUSD amount with 18 fixed decimals.\\n */\\n function setAutoAllocateThreshold(uint256 _threshold)\\n external\\n onlyGovernor\\n {\\n autoAllocateThreshold = _threshold;\\n emit AllocateThresholdUpdated(_threshold);\\n }\\n\\n /**\\n * @dev Set a minimum amount of OUSD in a mint or redeem that triggers a\\n * rebase\\n * @param _threshold OUSD amount with 18 fixed decimals.\\n */\\n function setRebaseThreshold(uint256 _threshold) external onlyGovernor {\\n rebaseThreshold = _threshold;\\n emit RebaseThresholdUpdated(_threshold);\\n }\\n\\n /**\\n * @dev Set address of Uniswap for performing liquidation of strategy reward\\n * tokens\\n * @param _address Address of Uniswap\\n */\\n function setUniswapAddr(address _address) external onlyGovernor {\\n uniswapAddr = _address;\\n emit UniswapUpdated(_address);\\n }\\n\\n /**\\n * @dev Set address of Strategist\\n * @param _address Address of Strategist\\n */\\n function setStrategistAddr(address _address) external onlyGovernor {\\n strategistAddr = _address;\\n emit StrategistUpdated(_address);\\n }\\n\\n /**\\n * @dev Set the default Strategy for an asset, i.e. the one which the asset\\n will be automatically allocated to and withdrawn from\\n * @param _asset Address of the asset\\n * @param _strategy Address of the Strategy\\n */\\n function setAssetDefaultStrategy(address _asset, address _strategy)\\n external\\n onlyGovernorOrStrategist\\n {\\n emit AssetDefaultStrategyUpdated(_asset, _strategy);\\n require(strategies[_strategy].isSupported, \\\"Strategy not approved\\\");\\n IStrategy strategy = IStrategy(_strategy);\\n require(assets[_asset].isSupported, \\\"Asset is not supported\\\");\\n require(\\n strategy.supportsAsset(_asset),\\n \\\"Asset not supported by Strategy\\\"\\n );\\n assetDefaultStrategies[_asset] = _strategy;\\n }\\n\\n /**\\n * @dev Add a supported asset to the contract, i.e. one that can be\\n * to mint OUSD.\\n * @param _asset Address of asset\\n */\\n function supportAsset(address _asset) external onlyGovernor {\\n require(!assets[_asset].isSupported, \\\"Asset already supported\\\");\\n\\n assets[_asset] = Asset({ isSupported: true });\\n allAssets.push(_asset);\\n\\n emit AssetSupported(_asset);\\n }\\n\\n /**\\n * @dev Add a strategy to the Vault.\\n * @param _addr Address of the strategy to add\\n */\\n function approveStrategy(address _addr) external onlyGovernor {\\n require(!strategies[_addr].isSupported, \\\"Strategy already approved\\\");\\n strategies[_addr] = Strategy({ isSupported: true, _deprecated: 0 });\\n allStrategies.push(_addr);\\n emit StrategyApproved(_addr);\\n }\\n\\n /**\\n * @dev Remove a strategy from the Vault. Removes all invested assets and\\n * returns them to the Vault.\\n * @param _addr Address of the strategy to remove\\n */\\n\\n function removeStrategy(address _addr) external onlyGovernor {\\n require(strategies[_addr].isSupported, \\\"Strategy not approved\\\");\\n\\n // Initialize strategyIndex with out of bounds result so function will\\n // revert if no valid index found\\n uint256 strategyIndex = allStrategies.length;\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n if (allStrategies[i] == _addr) {\\n strategyIndex = i;\\n break;\\n }\\n }\\n\\n if (strategyIndex < allStrategies.length) {\\n allStrategies[strategyIndex] = allStrategies[allStrategies.length -\\n 1];\\n allStrategies.pop();\\n\\n // Withdraw all assets\\n IStrategy strategy = IStrategy(_addr);\\n strategy.withdrawAll();\\n // Call harvest after withdraw in case withdraw triggers\\n // distribution of additional reward tokens (true for Compound)\\n _harvest(_addr);\\n emit StrategyRemoved(_addr);\\n }\\n\\n // Clean up struct in mapping, this can be removed later\\n // See https://github.com/OriginProtocol/origin-dollar/issues/324\\n strategies[_addr].isSupported = false;\\n }\\n\\n /**\\n * @notice Move assets from one Strategy to another\\n * @param _strategyFromAddress Address of Strategy to move assets from.\\n * @param _strategyToAddress Address of Strategy to move assets to.\\n * @param _assets Array of asset address that will be moved\\n * @param _amounts Array of amounts of each corresponding asset to move.\\n */\\n function reallocate(\\n address _strategyFromAddress,\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external onlyGovernorOrStrategist {\\n require(\\n strategies[_strategyFromAddress].isSupported,\\n \\\"Invalid from Strategy\\\"\\n );\\n require(\\n strategies[_strategyToAddress].isSupported,\\n \\\"Invalid to Strategy\\\"\\n );\\n require(_assets.length == _amounts.length, \\\"Parameter length mismatch\\\");\\n\\n IStrategy strategyFrom = IStrategy(_strategyFromAddress);\\n IStrategy strategyTo = IStrategy(_strategyToAddress);\\n\\n for (uint256 i = 0; i < _assets.length; i++) {\\n require(strategyTo.supportsAsset(_assets[i]), \\\"Asset unsupported\\\");\\n // Withdraw from Strategy and pass other Strategy as recipient\\n strategyFrom.withdraw(address(strategyTo), _assets[i], _amounts[i]);\\n }\\n // Tell new Strategy to deposit into protocol\\n strategyTo.depositAll();\\n }\\n\\n /**\\n * @dev Sets the maximum allowable difference between\\n * total supply and backing assets' value.\\n */\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor {\\n maxSupplyDiff = _maxSupplyDiff;\\n emit MaxSupplyDiffChanged(_maxSupplyDiff);\\n }\\n\\n /**\\n * @dev Sets the trusteeAddress that can receive a portion of yield.\\n * Setting to the zero address disables this feature.\\n */\\n function setTrusteeAddress(address _address) external onlyGovernor {\\n trusteeAddress = _address;\\n emit TrusteeAddressChanged(_address);\\n }\\n\\n /**\\n * @dev Sets the TrusteeFeeBps to the percentage of yield that should be\\n * received in basis points.\\n */\\n function setTrusteeFeeBps(uint256 _basis) external onlyGovernor {\\n require(_basis <= 5000, \\\"basis cannot exceed 50%\\\");\\n trusteeFeeBps = _basis;\\n emit TrusteeFeeBpsChanged(_basis);\\n }\\n\\n /***************************************\\n Pause\\n ****************************************/\\n\\n /**\\n * @dev Set the deposit paused flag to true to prevent rebasing.\\n */\\n function pauseRebase() external onlyGovernorOrStrategist {\\n rebasePaused = true;\\n emit RebasePaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to true to allow rebasing.\\n */\\n function unpauseRebase() external onlyGovernor {\\n rebasePaused = false;\\n emit RebaseUnpaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to true to prevent capital movement.\\n */\\n function pauseCapital() external onlyGovernorOrStrategist {\\n capitalPaused = true;\\n emit CapitalPaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to false to enable capital movement.\\n */\\n function unpauseCapital() external onlyGovernor {\\n capitalPaused = false;\\n emit CapitalUnpaused();\\n }\\n\\n /***************************************\\n Rewards\\n ****************************************/\\n\\n /**\\n * @dev Transfer token to governor. Intended for recovering tokens stuck in\\n * contract, i.e. mistaken sends.\\n * @param _asset Address for the asset\\n * @param _amount Amount of the asset to transfer\\n */\\n function transferToken(address _asset, uint256 _amount)\\n external\\n onlyGovernor\\n {\\n require(!assets[_asset].isSupported, \\\"Only unsupported assets\\\");\\n IERC20(_asset).safeTransfer(governor(), _amount);\\n }\\n\\n /**\\n * @dev Collect reward tokens from all strategies and swap for supported\\n * stablecoin via Uniswap\\n */\\n function harvest() external onlyGovernorOrStrategist {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n _harvest(allStrategies[i]);\\n }\\n }\\n\\n /**\\n * @dev Collect reward tokens for a specific strategy and swap for supported\\n * stablecoin via Uniswap. Called from the vault.\\n * @param _strategyAddr Address of the strategy to collect rewards from\\n */\\n function harvest(address _strategyAddr)\\n external\\n onlyVaultOrGovernorOrStrategist\\n returns (uint256[] memory)\\n {\\n return _harvest(_strategyAddr);\\n }\\n\\n /**\\n * @dev Collect reward tokens from a single strategy and swap them for a\\n * supported stablecoin via Uniswap\\n * @param _strategyAddr Address of the strategy to collect rewards from\\n */\\n function _harvest(address _strategyAddr)\\n internal\\n returns (uint256[] memory)\\n {\\n IStrategy strategy = IStrategy(_strategyAddr);\\n address rewardTokenAddress = strategy.rewardTokenAddress();\\n if (rewardTokenAddress != address(0)) {\\n strategy.collectRewardToken();\\n\\n if (uniswapAddr != address(0)) {\\n IERC20 rewardToken = IERC20(strategy.rewardTokenAddress());\\n uint256 rewardTokenAmount = rewardToken.balanceOf(\\n address(this)\\n );\\n if (rewardTokenAmount > 0) {\\n // Give Uniswap full amount allowance\\n rewardToken.safeApprove(uniswapAddr, 0);\\n rewardToken.safeApprove(uniswapAddr, rewardTokenAmount);\\n\\n // Uniswap redemption path\\n address[] memory path = new address[](3);\\n path[0] = strategy.rewardTokenAddress();\\n path[1] = IUniswapV2Router(uniswapAddr).WETH();\\n path[2] = allAssets[1]; // USDT\\n\\n return\\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\\n rewardTokenAmount,\\n uint256(0),\\n path,\\n address(this),\\n now.add(1800)\\n );\\n }\\n }\\n }\\n }\\n\\n /***************************************\\n Pricing\\n ****************************************/\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Using Min since min is what we use for mint pricing\\n * @param symbol String symbol of the asset\\n * @return uint256 USD price of 1 of the asset\\n */\\n function priceUSDMint(string calldata symbol)\\n external\\n view\\n returns (uint256)\\n {\\n return _priceUSDMint(symbol);\\n }\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Using Min since min is what we use for mint pricing\\n * @param symbol String symbol of the asset\\n * @return uint256 USD price of 1 of the asset\\n */\\n function _priceUSDMint(string memory symbol)\\n internal\\n view\\n returns (uint256)\\n {\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return IMinMaxOracle(priceProvider).priceMin(symbol).scaleBy(10);\\n }\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Using Max since max is what we use for redeem pricing\\n * @param symbol String symbol of the asset\\n * @return uint256 USD price of 1 of the asset\\n */\\n function priceUSDRedeem(string calldata symbol)\\n external\\n view\\n returns (uint256)\\n {\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return _priceUSDRedeem(symbol);\\n }\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Using Max since max is what we use for redeem pricing\\n * @param symbol String symbol of the asset\\n * @return uint256 USD price of 1 of the asset\\n */\\n function _priceUSDRedeem(string memory symbol)\\n internal\\n view\\n returns (uint256)\\n {\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return IMinMaxOracle(priceProvider).priceMax(symbol).scaleBy(10);\\n }\\n}\\n\",\"keccak256\":\"0x060d1e1f6e54a00e2b875274ebb432ffec38c5915e3bac54109f45fcb21070c2\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD VaultStorage Contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\n\\ncontract VaultStorage is Initializable, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n using SafeMath for int256;\\n using SafeERC20 for IERC20;\\n\\n event AssetSupported(address _asset);\\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\\n event PriceProviderUpdated(address _priceProvider);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event UniswapUpdated(address _address);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n\\n // Assets supported by the Vault, i.e. Stablecoins\\n struct Asset {\\n bool isSupported;\\n }\\n mapping(address => Asset) assets;\\n address[] allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n mapping(address => Strategy) strategies;\\n address[] allStrategies;\\n\\n // Address of the Oracle price provider contract\\n address public priceProvider;\\n // Pausing bools\\n bool public rebasePaused = false;\\n bool public capitalPaused = true;\\n // Redemption fee in basis points\\n uint256 public redeemFeeBps;\\n // Buffer of assets to keep in Vault to handle (most) withdrawals\\n uint256 public vaultBuffer;\\n // Mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n // Mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n OUSD oUSD;\\n\\n //keccak256(\\\"OUSD.vault.governor.admin.impl\\\");\\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\\n\\n // Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n // Address of Uniswap\\n address public uniswapAddr = address(0);\\n\\n // Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n // Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n mapping(address => address) public assetDefaultStrategies;\\n\\n uint256 public maxSupplyDiff;\\n\\n // Trustee address that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n // Amount of yield collected in basis points\\n uint256 public trusteeFeeBps;\\n\\n /**\\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\\n * @param newImpl address of the implementation\\n */\\n function setAdminImpl(address newImpl) external onlyGovernor {\\n require(\\n Address.isContract(newImpl),\\n \\\"new implementation is not a contract\\\"\\n );\\n bytes32 position = adminImplPosition;\\n assembly {\\n sstore(position, newImpl)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x02d224b70c086a3df5cf22792721aed5f278ddf4bc7b98b67ac9c38c767760a0\"}},\"version\":1}", - "bytecode": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b60008051602062002fdc83398151915255565b60008051602062002fdc8339815191525490565b612eea80620000f26000396000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c80635d36b19011610146578063aea173d5116100c3578063c5f0084111610087578063c5f0084114610773578063c7af33521461077b578063d38bfff414610783578063e6cc5432146107a9578063eb03654b146107b1578063fc0cfeee146107ce5761025e565b8063aea173d5146106dd578063b2c9336d14610703578063b888879e14610720578063b890ebf614610728578063bc90106b146107455761025e565b80638e510b521161010a5780638e510b52146106825780638ec489a21461068a57806394828ffd146106a75780639fa1826e146106af578063a403e4d5146106b75761025e565b80635d36b190146104f2578063663e64ce146104fa578063686b37ca14610517578063773540b3146105855780637fe2d393146105ab5761025e565b806329a903ec116101df5780634641257d116101a35780634641257d1461049057806349c1d54d146104985780634cd55c2d146104a057806352d38e5d146104c657806353ca9f24146104ce578063570d8e1d146104ea5761025e565b806329a903ec146103a85780632da845a814610416578063372aa2241461043c5780633b8ae397146104625780633dbc911f146104885761025e565b80631072cbea116102265780631072cbea1461033e578063128a8b051461036a578063175188e8146103725780631edfe3da14610398578063207134b0146103a05761025e565b806309f49bf51461026357806309f6442c1461026d5780630acbda75146102875780630c340a24146102a45780630e5c011e146102c8575b600080fd5b61026b6107f4565b005b610275610873565b60408051918252519081900360200190f35b61026b6004803603602081101561029d57600080fd5b5035610879565b6102ac610952565b604080516001600160a01b039092168252519081900360200190f35b6102ee600480360360208110156102de57600080fd5b50356001600160a01b0316610961565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561032a578181015183820152602001610312565b505050509050019250505060405180910390f35b61026b6004803603604081101561035457600080fd5b506001600160a01b0381351690602001356109d5565b6102ac610ab0565b61026b6004803603602081101561038857600080fd5b50356001600160a01b0316610abf565b610275610d23565b610275610d29565b610275600480360360208110156103be57600080fd5b810190602081018135600160201b8111156103d857600080fd5b8201836020820111156103ea57600080fd5b803590602001918460018302840111600160201b8311171561040b57600080fd5b509092509050610d2f565b61026b6004803603602081101561042c57600080fd5b50356001600160a01b0316610d79565b61026b6004803603602081101561045257600080fd5b50356001600160a01b0316610e14565b61026b6004803603602081101561047857600080fd5b50356001600160a01b0316610eaf565b61026b61101c565b61026b6110b1565b6102ac61114b565b61026b600480360360208110156104b657600080fd5b50356001600160a01b031661115a565b6102756112b7565b6104d66112bd565b604080519115158252519081900360200190f35b6102ac6112cd565b61026b6112dc565b61026b6004803603602081101561051057600080fd5b503561133e565b6102756004803603602081101561052d57600080fd5b810190602081018135600160201b81111561054757600080fd5b82018360208201111561055957600080fd5b803590602001918460018302840111600160201b8311171561057a57600080fd5b5090925090506113c0565b61026b6004803603602081101561059b57600080fd5b50356001600160a01b0316611401565b61026b600480360360808110156105c157600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156105f457600080fd5b82018360208201111561060657600080fd5b803590602001918460208302840111600160201b8311171561062757600080fd5b919390929091602081019035600160201b81111561064457600080fd5b82018360208201111561065657600080fd5b803590602001918460208302840111600160201b8311171561067757600080fd5b50909250905061149c565b610275611827565b61026b600480360360208110156106a057600080fd5b503561182d565b61026b6118fc565b61027561197b565b6102ac600480360360208110156106cd57600080fd5b50356001600160a01b0316611981565b61026b600480360360208110156106f357600080fd5b50356001600160a01b031661199c565b61026b6004803603602081101561071957600080fd5b5035611a37565b6102ac611ab9565b61026b6004803603602081101561073e57600080fd5b5035611ac8565b61026b6004803603604081101561075b57600080fd5b506001600160a01b0381358116916020013516611b4a565b61026b611db5565b6104d6611e4a565b61026b6004803603602081101561079957600080fd5b50356001600160a01b0316611e6d565b6104d6611f07565b61026b600480360360208110156107c757600080fd5b5035611f17565b61026b600480360360208110156107e457600080fd5b50356001600160a01b0316611f99565b6107fc611e4a565b61083b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6037805460ff60a01b191690556040517fbc044409505c95b6b851433df96e1beae715c909d8e7c1d6d7ab783300d4e3b990600090a1565b60385481565b610881611e4a565b6108c0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611388811115610917576040805162461bcd60e51b815260206004820152601760248201527f62617369732063616e6e6f742065786365656420353025000000000000000000604482015290519081900360640190fd5b60438190556040805182815290517f56287a45051933ea374811b3d5d165033047be5572cac676f7c28b8be4f746c79181900360200190a150565b600061095c612048565b905090565b60603330148061097b5750603f546001600160a01b031633145b806109895750610989611e4a565b6109c45760405162461bcd60e51b8152600401808060200182810382526030815260200180612df66030913960400191505060405180910390fd5b6109cd8261206d565b90505b919050565b6109dd611e4a565b610a1c576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526033602052604090205460ff1615610a8a576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c7920756e737570706f7274656420617373657473000000000000000000604482015290519081900360640190fd5b610aac610a95610952565b6001600160a01b038416908363ffffffff6125ab16565b5050565b603e546001600160a01b031681565b610ac7611e4a565b610b06576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff16610b6b576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b60365460005b603654811015610bbd57826001600160a01b031660368281548110610b9257fe5b6000918252602090912001546001600160a01b03161415610bb557809150610bbd565b600101610b71565b50603654811015610d0157603680546000198101908110610bda57fe5b600091825260209091200154603680546001600160a01b039092169183908110610c0057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506036805480610c3957fe5b6001900381819060005260206000200160006101000a8154906001600160a01b03021916905590556000829050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ca157600080fd5b505af1158015610cb5573d6000803e3d6000fd5b50505050610cc28361206d565b50604080516001600160a01b038516815290517f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea49181900360200190a1505b506001600160a01b03166000908152603560205260409020805460ff19169055565b60395481565b60435481565b6000610d7083838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061260292505050565b90505b92915050565b610d81611e4a565b610dc0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1e4af5ac389e8cde1bdaa6830881b6c987c62a45cfb3b33d27d805cde3b577509181900360200190a150565b610e1c611e4a565b610e5b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603780546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb266add5f3044b17d27db796af992cecbe413921b4e8aaaee03c719e16b9806a9181900360200190a150565b610eb7611e4a565b610ef6576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff1615610f64576040805162461bcd60e51b815260206004820152601960248201527f537472617465677920616c726561647920617070726f76656400000000000000604482015290519081900360640190fd5b6040805180820182526001808252600060208084018281526001600160a01b038716808452603583528684209551865460ff19169015151786559051948401949094556036805493840181559091527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890910180546001600160a01b03191683179055825191825291517f960dd94cbb79169f09a4e445d58b895df2d9bffa5b31055d0932d801724a20d1929181900390910190a150565b603f546001600160a01b03163314806110385750611038611e4a565b6110735760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6037805460ff60a81b1916600160a81b1790556040517f71f0e5b62f846a22e0b4d159e516e62fa9c2b8eb570be15f83e67d98a2ee51e090600090a1565b603f546001600160a01b03163314806110cd57506110cd611e4a565b6111085760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b60005b6036548110156111485761113f6036828154811061112557fe5b6000918252602090912001546001600160a01b031661206d565b5060010161110b565b50565b6042546001600160a01b031681565b611162611e4a565b6111a1576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526033602052604090205460ff161561120f576040805162461bcd60e51b815260206004820152601760248201527f417373657420616c726561647920737570706f72746564000000000000000000604482015290519081900360640190fd5b604080516020808201835260018083526001600160a01b0385166000818152603384528581209451855460ff1916901515179094556034805492830181559093527f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c10180546001600160a01b03191683179055825191825291517f4f1ac48525e50059cc1cc6e0e1940ece0dd653a4db4841538d6aef036be2fb7b929181900390910190a150565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b6112e46126ef565b6001600160a01b0316336001600160a01b0316146113335760405162461bcd60e51b8152600401808060200182810382526030815260200180612e866030913960400191505060405180910390fd5b61133c33612714565b565b611346611e4a565b611385576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b60418190556040805182815290517f95201f9c21f26877223b1ff4073936a6484c35495649e60e55730497aeb60d939181900360200190a150565b6000610d7083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127bf92505050565b611409611e4a565b611448576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603f80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee9181900360200190a150565b603f546001600160a01b03163314806114b857506114b8611e4a565b6114f35760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6001600160a01b03861660009081526035602052604090205460ff16611558576040805162461bcd60e51b8152602060048201526015602482015274496e76616c69642066726f6d20537472617465677960581b604482015290519081900360640190fd5b6001600160a01b03851660009081526035602052604090205460ff166115bb576040805162461bcd60e51b8152602060048201526013602482015272496e76616c696420746f20537472617465677960681b604482015290519081900360640190fd5b82811461160f576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b858560005b858110156117c957816001600160a01b031663aa388af688888481811061163757fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561168d57600080fd5b505afa1580156116a1573d6000803e3d6000fd5b505050506040513d60208110156116b757600080fd5b50516116fe576040805162461bcd60e51b8152602060048201526011602482015270105cdcd95d081d5b9cdd5c1c1bdc9d1959607a1b604482015290519081900360640190fd5b826001600160a01b031663d9caed128389898581811061171a57fe5b905060200201356001600160a01b031688888681811061173657fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b1580156117a557600080fd5b505af11580156117b9573d6000803e3d6000fd5b5050600190920191506116149050565b50806001600160a01b031663de5f62686040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b505050505050505050505050565b60415481565b611835611e4a565b611874576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b670de0b6b3a76400008111156118c1576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015290519081900360640190fd5b60398190556040805182815290517f41ecb23a0e7865b25f38c268b7c3012220d822929e9edff07326e89d5bb822b59181900360200190a150565b611904611e4a565b611943576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6037805460ff60a81b191690556040517f891ebab18da80ebeeea06b1b1cede098329c4c008906a98370c2ac7a80b571cb90600090a1565b603a5481565b6040602081905260009182529020546001600160a01b031681565b6119a4611e4a565b6119e3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603e80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b611a3f611e4a565b611a7e576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603a8190556040805182815290517f2ec5fb5a3d2703edc461252d92ccd2799c3c74f01d97212b20388207fa17ae459181900360200190a150565b6037546001600160a01b031681565b611ad0611e4a565b611b0f576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603b8190556040805182815290517f39367850377ac04920a9a670f2180e7a94d83b15ad302e59875ec58fd10bd37d9181900360200190a150565b603f546001600160a01b0316331480611b665750611b66611e4a565b611ba15760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b604080516001600160a01b0380851682528316602082015281517fba58ce12801c949fa65f41c46ed108671c219baf945fa48d21026cea99ff252a929181900390910190a16001600160a01b03811660009081526035602052604090205460ff16611c4b576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260336020526040902054819060ff16611cb3576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b806001600160a01b031663aa388af6846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611d0957600080fd5b505afa158015611d1d573d6000803e3d6000fd5b505050506040513d6020811015611d3357600080fd5b5051611d86576040805162461bcd60e51b815260206004820152601f60248201527f4173736574206e6f7420737570706f7274656420627920537472617465677900604482015290519081900360640190fd5b506001600160a01b03918216600090815260406020819052902080546001600160a01b03191691909216179055565b603f546001600160a01b0316331480611dd15750611dd1611e4a565b611e0c5760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6037805460ff60a01b1916600160a01b1790556040517f8cff26a5985614b3d30629cc4ab83824bf115aec971b718d8f2f99562032e97290600090a1565b6000611e54612048565b6001600160a01b0316336001600160a01b031614905090565b611e75611e4a565b611eb4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611ebd81612827565b806001600160a01b0316611ecf612048565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b603754600160a81b900460ff1681565b611f1f611e4a565b611f5e576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b60388190556040805182815290517fd6c7508d6658ccee36b7b7d7fd72e5cbaeefb40c64eff24e9ae7470e846304ee9181900360200190a150565b611fa1611e4a565b611fe0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611fe98161284b565b6120245760405162461bcd60e51b8152600401808060200182810382526024815260200180612d696024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606060008290506000816001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156120af57600080fd5b505afa1580156120c3573d6000803e3d6000fd5b505050506040513d60208110156120d957600080fd5b505190506001600160a01b038116156125a457816001600160a01b0316630242241d6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561212757600080fd5b505af115801561213b573d6000803e3d6000fd5b5050603e546001600160a01b03161591506125a49050576000826001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b15801561218d57600080fd5b505afa1580156121a1573d6000803e3d6000fd5b505050506040513d60208110156121b757600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561220557600080fd5b505afa158015612219573d6000803e3d6000fd5b505050506040513d602081101561222f57600080fd5b5051905080156125a157603e5461225a906001600160a01b038481169116600063ffffffff61288716565b603e5461227a906001600160a01b0384811691168363ffffffff61288716565b60408051600380825260808201909252606091602082018380388339019050509050846001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156122d557600080fd5b505afa1580156122e9573d6000803e3d6000fd5b505050506040513d60208110156122ff57600080fd5b50518151829060009061230e57fe5b6001600160a01b03928316602091820292909201810191909152603e54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561236257600080fd5b505afa158015612376573d6000803e3d6000fd5b505050506040513d602081101561238c57600080fd5b505181518290600190811061239d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060346001815481106123cb57fe5b9060005260206000200160009054906101000a90046001600160a01b0316816002815181106123f657fe5b6001600160a01b039283166020918202929092010152603e54166338ed1739836000843061242c4261070863ffffffff61299a16565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b838110156124a557818101518382015260200161248d565b505050509050019650505050505050600060405180830381600087803b1580156124ce57600080fd5b505af11580156124e2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561250b57600080fd5b8101908080516040519392919084600160201b82111561252a57600080fd5b90830190602082018581111561253f57600080fd5b82518660208202830111600160201b8211171561255b57600080fd5b82525081516020918201928201910280838360005b83811015612588578181015183820152602001612570565b50505050905001604052505050955050505050506109d0565b50505b5050919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526125fd9084906129f4565b505050565b603754604051637bf0c21560e01b81526020600482018181528451602484015284516000946109cd94600a946001600160a01b0390921693637bf0c21593899391928392604490910191908501908083838d5b8381101561266d578181015183820152602001612655565b50505050905090810190601f16801561269a5780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b1580156126b757600080fd5b505afa1580156126cb573d6000803e3d6000fd5b505050506040513d60208110156126e157600080fd5b50519063ffffffff612bb216565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b03811661276f576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316612781612048565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a361114881612c0c565b60375460405163019af6bf60e41b81526020600482018181528451602484015284516000946109cd94600a946001600160a01b03909216936319af6bf093899391928392604490910191908501908083838d831561266d578181015183820152602001612655565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061287f57508115155b949350505050565b80158061290d575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156128df57600080fd5b505afa1580156128f3573d6000803e3d6000fd5b505050506040513d602081101561290957600080fd5b5051155b6129485760405162461bcd60e51b8152600401808060200182810382526036815260200180612e506036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526125fd9084906129f4565b600082820183811015610d70576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612a06826001600160a01b031661284b565b612a57576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612a955780518252601f199092019160209182019101612a76565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b509150915081612b53576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612bac57808060200190516020811015612b6f57600080fd5b5051612bac5760405162461bcd60e51b815260040180806020018281038252602a815260200180612e26602a913960400191505060405180910390fd5b50505050565b6000808260000b1315612bdd57612bd683600084900b600a0a63ffffffff612c3016565b9250612c05565b60008260000b1215612c0557612c02836000848103900b600a0a63ffffffff612c8916565b92505b5090919050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b600082612c3f57506000610d73565b82820282848281612c4c57fe5b0414610d705760405162461bcd60e51b8152600401808060200182810382526021815260200180612dd56021913960400191505060405180910390fd5b6000610d7083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183612d525760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d17578181015183820152602001612cff565b50505050905090810190601f168015612d445780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612d5e57fe5b049594505050505056fe6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637443616c6c6572206973206e6f74207468652053747261746567697374206f7220476f7665726e6f7243616c6c6572206973206e6f742074686520476f7665726e6f72000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f7420746865205661756c742c20476f7665726e6f722c206f7220537472617465676973745361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158202d9460819698975a6c9f01af70fc6f240ae6d45252536f47eb9a05cb1514ebb464736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061025e5760003560e01c80635d36b19011610146578063aea173d5116100c3578063c5f0084111610087578063c5f0084114610773578063c7af33521461077b578063d38bfff414610783578063e6cc5432146107a9578063eb03654b146107b1578063fc0cfeee146107ce5761025e565b8063aea173d5146106dd578063b2c9336d14610703578063b888879e14610720578063b890ebf614610728578063bc90106b146107455761025e565b80638e510b521161010a5780638e510b52146106825780638ec489a21461068a57806394828ffd146106a75780639fa1826e146106af578063a403e4d5146106b75761025e565b80635d36b190146104f2578063663e64ce146104fa578063686b37ca14610517578063773540b3146105855780637fe2d393146105ab5761025e565b806329a903ec116101df5780634641257d116101a35780634641257d1461049057806349c1d54d146104985780634cd55c2d146104a057806352d38e5d146104c657806353ca9f24146104ce578063570d8e1d146104ea5761025e565b806329a903ec146103a85780632da845a814610416578063372aa2241461043c5780633b8ae397146104625780633dbc911f146104885761025e565b80631072cbea116102265780631072cbea1461033e578063128a8b051461036a578063175188e8146103725780631edfe3da14610398578063207134b0146103a05761025e565b806309f49bf51461026357806309f6442c1461026d5780630acbda75146102875780630c340a24146102a45780630e5c011e146102c8575b600080fd5b61026b6107f4565b005b610275610873565b60408051918252519081900360200190f35b61026b6004803603602081101561029d57600080fd5b5035610879565b6102ac610952565b604080516001600160a01b039092168252519081900360200190f35b6102ee600480360360208110156102de57600080fd5b50356001600160a01b0316610961565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561032a578181015183820152602001610312565b505050509050019250505060405180910390f35b61026b6004803603604081101561035457600080fd5b506001600160a01b0381351690602001356109d5565b6102ac610ab0565b61026b6004803603602081101561038857600080fd5b50356001600160a01b0316610abf565b610275610d23565b610275610d29565b610275600480360360208110156103be57600080fd5b810190602081018135600160201b8111156103d857600080fd5b8201836020820111156103ea57600080fd5b803590602001918460018302840111600160201b8311171561040b57600080fd5b509092509050610d2f565b61026b6004803603602081101561042c57600080fd5b50356001600160a01b0316610d79565b61026b6004803603602081101561045257600080fd5b50356001600160a01b0316610e14565b61026b6004803603602081101561047857600080fd5b50356001600160a01b0316610eaf565b61026b61101c565b61026b6110b1565b6102ac61114b565b61026b600480360360208110156104b657600080fd5b50356001600160a01b031661115a565b6102756112b7565b6104d66112bd565b604080519115158252519081900360200190f35b6102ac6112cd565b61026b6112dc565b61026b6004803603602081101561051057600080fd5b503561133e565b6102756004803603602081101561052d57600080fd5b810190602081018135600160201b81111561054757600080fd5b82018360208201111561055957600080fd5b803590602001918460018302840111600160201b8311171561057a57600080fd5b5090925090506113c0565b61026b6004803603602081101561059b57600080fd5b50356001600160a01b0316611401565b61026b600480360360808110156105c157600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156105f457600080fd5b82018360208201111561060657600080fd5b803590602001918460208302840111600160201b8311171561062757600080fd5b919390929091602081019035600160201b81111561064457600080fd5b82018360208201111561065657600080fd5b803590602001918460208302840111600160201b8311171561067757600080fd5b50909250905061149c565b610275611827565b61026b600480360360208110156106a057600080fd5b503561182d565b61026b6118fc565b61027561197b565b6102ac600480360360208110156106cd57600080fd5b50356001600160a01b0316611981565b61026b600480360360208110156106f357600080fd5b50356001600160a01b031661199c565b61026b6004803603602081101561071957600080fd5b5035611a37565b6102ac611ab9565b61026b6004803603602081101561073e57600080fd5b5035611ac8565b61026b6004803603604081101561075b57600080fd5b506001600160a01b0381358116916020013516611b4a565b61026b611db5565b6104d6611e4a565b61026b6004803603602081101561079957600080fd5b50356001600160a01b0316611e6d565b6104d6611f07565b61026b600480360360208110156107c757600080fd5b5035611f17565b61026b600480360360208110156107e457600080fd5b50356001600160a01b0316611f99565b6107fc611e4a565b61083b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6037805460ff60a01b191690556040517fbc044409505c95b6b851433df96e1beae715c909d8e7c1d6d7ab783300d4e3b990600090a1565b60385481565b610881611e4a565b6108c0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611388811115610917576040805162461bcd60e51b815260206004820152601760248201527f62617369732063616e6e6f742065786365656420353025000000000000000000604482015290519081900360640190fd5b60438190556040805182815290517f56287a45051933ea374811b3d5d165033047be5572cac676f7c28b8be4f746c79181900360200190a150565b600061095c612048565b905090565b60603330148061097b5750603f546001600160a01b031633145b806109895750610989611e4a565b6109c45760405162461bcd60e51b8152600401808060200182810382526030815260200180612df66030913960400191505060405180910390fd5b6109cd8261206d565b90505b919050565b6109dd611e4a565b610a1c576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526033602052604090205460ff1615610a8a576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c7920756e737570706f7274656420617373657473000000000000000000604482015290519081900360640190fd5b610aac610a95610952565b6001600160a01b038416908363ffffffff6125ab16565b5050565b603e546001600160a01b031681565b610ac7611e4a565b610b06576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff16610b6b576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b60365460005b603654811015610bbd57826001600160a01b031660368281548110610b9257fe5b6000918252602090912001546001600160a01b03161415610bb557809150610bbd565b600101610b71565b50603654811015610d0157603680546000198101908110610bda57fe5b600091825260209091200154603680546001600160a01b039092169183908110610c0057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506036805480610c3957fe5b6001900381819060005260206000200160006101000a8154906001600160a01b03021916905590556000829050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ca157600080fd5b505af1158015610cb5573d6000803e3d6000fd5b50505050610cc28361206d565b50604080516001600160a01b038516815290517f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea49181900360200190a1505b506001600160a01b03166000908152603560205260409020805460ff19169055565b60395481565b60435481565b6000610d7083838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061260292505050565b90505b92915050565b610d81611e4a565b610dc0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1e4af5ac389e8cde1bdaa6830881b6c987c62a45cfb3b33d27d805cde3b577509181900360200190a150565b610e1c611e4a565b610e5b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603780546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb266add5f3044b17d27db796af992cecbe413921b4e8aaaee03c719e16b9806a9181900360200190a150565b610eb7611e4a565b610ef6576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff1615610f64576040805162461bcd60e51b815260206004820152601960248201527f537472617465677920616c726561647920617070726f76656400000000000000604482015290519081900360640190fd5b6040805180820182526001808252600060208084018281526001600160a01b038716808452603583528684209551865460ff19169015151786559051948401949094556036805493840181559091527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890910180546001600160a01b03191683179055825191825291517f960dd94cbb79169f09a4e445d58b895df2d9bffa5b31055d0932d801724a20d1929181900390910190a150565b603f546001600160a01b03163314806110385750611038611e4a565b6110735760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6037805460ff60a81b1916600160a81b1790556040517f71f0e5b62f846a22e0b4d159e516e62fa9c2b8eb570be15f83e67d98a2ee51e090600090a1565b603f546001600160a01b03163314806110cd57506110cd611e4a565b6111085760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b60005b6036548110156111485761113f6036828154811061112557fe5b6000918252602090912001546001600160a01b031661206d565b5060010161110b565b50565b6042546001600160a01b031681565b611162611e4a565b6111a1576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526033602052604090205460ff161561120f576040805162461bcd60e51b815260206004820152601760248201527f417373657420616c726561647920737570706f72746564000000000000000000604482015290519081900360640190fd5b604080516020808201835260018083526001600160a01b0385166000818152603384528581209451855460ff1916901515179094556034805492830181559093527f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c10180546001600160a01b03191683179055825191825291517f4f1ac48525e50059cc1cc6e0e1940ece0dd653a4db4841538d6aef036be2fb7b929181900390910190a150565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b6112e46126ef565b6001600160a01b0316336001600160a01b0316146113335760405162461bcd60e51b8152600401808060200182810382526030815260200180612e866030913960400191505060405180910390fd5b61133c33612714565b565b611346611e4a565b611385576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b60418190556040805182815290517f95201f9c21f26877223b1ff4073936a6484c35495649e60e55730497aeb60d939181900360200190a150565b6000610d7083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127bf92505050565b611409611e4a565b611448576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603f80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee9181900360200190a150565b603f546001600160a01b03163314806114b857506114b8611e4a565b6114f35760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6001600160a01b03861660009081526035602052604090205460ff16611558576040805162461bcd60e51b8152602060048201526015602482015274496e76616c69642066726f6d20537472617465677960581b604482015290519081900360640190fd5b6001600160a01b03851660009081526035602052604090205460ff166115bb576040805162461bcd60e51b8152602060048201526013602482015272496e76616c696420746f20537472617465677960681b604482015290519081900360640190fd5b82811461160f576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b858560005b858110156117c957816001600160a01b031663aa388af688888481811061163757fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561168d57600080fd5b505afa1580156116a1573d6000803e3d6000fd5b505050506040513d60208110156116b757600080fd5b50516116fe576040805162461bcd60e51b8152602060048201526011602482015270105cdcd95d081d5b9cdd5c1c1bdc9d1959607a1b604482015290519081900360640190fd5b826001600160a01b031663d9caed128389898581811061171a57fe5b905060200201356001600160a01b031688888681811061173657fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b1580156117a557600080fd5b505af11580156117b9573d6000803e3d6000fd5b5050600190920191506116149050565b50806001600160a01b031663de5f62686040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b505050505050505050505050565b60415481565b611835611e4a565b611874576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b670de0b6b3a76400008111156118c1576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015290519081900360640190fd5b60398190556040805182815290517f41ecb23a0e7865b25f38c268b7c3012220d822929e9edff07326e89d5bb822b59181900360200190a150565b611904611e4a565b611943576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6037805460ff60a81b191690556040517f891ebab18da80ebeeea06b1b1cede098329c4c008906a98370c2ac7a80b571cb90600090a1565b603a5481565b6040602081905260009182529020546001600160a01b031681565b6119a4611e4a565b6119e3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603e80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b611a3f611e4a565b611a7e576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603a8190556040805182815290517f2ec5fb5a3d2703edc461252d92ccd2799c3c74f01d97212b20388207fa17ae459181900360200190a150565b6037546001600160a01b031681565b611ad0611e4a565b611b0f576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603b8190556040805182815290517f39367850377ac04920a9a670f2180e7a94d83b15ad302e59875ec58fd10bd37d9181900360200190a150565b603f546001600160a01b0316331480611b665750611b66611e4a565b611ba15760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b604080516001600160a01b0380851682528316602082015281517fba58ce12801c949fa65f41c46ed108671c219baf945fa48d21026cea99ff252a929181900390910190a16001600160a01b03811660009081526035602052604090205460ff16611c4b576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260336020526040902054819060ff16611cb3576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b806001600160a01b031663aa388af6846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611d0957600080fd5b505afa158015611d1d573d6000803e3d6000fd5b505050506040513d6020811015611d3357600080fd5b5051611d86576040805162461bcd60e51b815260206004820152601f60248201527f4173736574206e6f7420737570706f7274656420627920537472617465677900604482015290519081900360640190fd5b506001600160a01b03918216600090815260406020819052902080546001600160a01b03191691909216179055565b603f546001600160a01b0316331480611dd15750611dd1611e4a565b611e0c5760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6037805460ff60a01b1916600160a01b1790556040517f8cff26a5985614b3d30629cc4ab83824bf115aec971b718d8f2f99562032e97290600090a1565b6000611e54612048565b6001600160a01b0316336001600160a01b031614905090565b611e75611e4a565b611eb4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611ebd81612827565b806001600160a01b0316611ecf612048565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b603754600160a81b900460ff1681565b611f1f611e4a565b611f5e576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b60388190556040805182815290517fd6c7508d6658ccee36b7b7d7fd72e5cbaeefb40c64eff24e9ae7470e846304ee9181900360200190a150565b611fa1611e4a565b611fe0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611fe98161284b565b6120245760405162461bcd60e51b8152600401808060200182810382526024815260200180612d696024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606060008290506000816001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156120af57600080fd5b505afa1580156120c3573d6000803e3d6000fd5b505050506040513d60208110156120d957600080fd5b505190506001600160a01b038116156125a457816001600160a01b0316630242241d6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561212757600080fd5b505af115801561213b573d6000803e3d6000fd5b5050603e546001600160a01b03161591506125a49050576000826001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b15801561218d57600080fd5b505afa1580156121a1573d6000803e3d6000fd5b505050506040513d60208110156121b757600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561220557600080fd5b505afa158015612219573d6000803e3d6000fd5b505050506040513d602081101561222f57600080fd5b5051905080156125a157603e5461225a906001600160a01b038481169116600063ffffffff61288716565b603e5461227a906001600160a01b0384811691168363ffffffff61288716565b60408051600380825260808201909252606091602082018380388339019050509050846001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156122d557600080fd5b505afa1580156122e9573d6000803e3d6000fd5b505050506040513d60208110156122ff57600080fd5b50518151829060009061230e57fe5b6001600160a01b03928316602091820292909201810191909152603e54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561236257600080fd5b505afa158015612376573d6000803e3d6000fd5b505050506040513d602081101561238c57600080fd5b505181518290600190811061239d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060346001815481106123cb57fe5b9060005260206000200160009054906101000a90046001600160a01b0316816002815181106123f657fe5b6001600160a01b039283166020918202929092010152603e54166338ed1739836000843061242c4261070863ffffffff61299a16565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b838110156124a557818101518382015260200161248d565b505050509050019650505050505050600060405180830381600087803b1580156124ce57600080fd5b505af11580156124e2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561250b57600080fd5b8101908080516040519392919084600160201b82111561252a57600080fd5b90830190602082018581111561253f57600080fd5b82518660208202830111600160201b8211171561255b57600080fd5b82525081516020918201928201910280838360005b83811015612588578181015183820152602001612570565b50505050905001604052505050955050505050506109d0565b50505b5050919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526125fd9084906129f4565b505050565b603754604051637bf0c21560e01b81526020600482018181528451602484015284516000946109cd94600a946001600160a01b0390921693637bf0c21593899391928392604490910191908501908083838d5b8381101561266d578181015183820152602001612655565b50505050905090810190601f16801561269a5780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b1580156126b757600080fd5b505afa1580156126cb573d6000803e3d6000fd5b505050506040513d60208110156126e157600080fd5b50519063ffffffff612bb216565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b03811661276f576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316612781612048565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a361114881612c0c565b60375460405163019af6bf60e41b81526020600482018181528451602484015284516000946109cd94600a946001600160a01b03909216936319af6bf093899391928392604490910191908501908083838d831561266d578181015183820152602001612655565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061287f57508115155b949350505050565b80158061290d575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156128df57600080fd5b505afa1580156128f3573d6000803e3d6000fd5b505050506040513d602081101561290957600080fd5b5051155b6129485760405162461bcd60e51b8152600401808060200182810382526036815260200180612e506036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526125fd9084906129f4565b600082820183811015610d70576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612a06826001600160a01b031661284b565b612a57576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612a955780518252601f199092019160209182019101612a76565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b509150915081612b53576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612bac57808060200190516020811015612b6f57600080fd5b5051612bac5760405162461bcd60e51b815260040180806020018281038252602a815260200180612e26602a913960400191505060405180910390fd5b50505050565b6000808260000b1315612bdd57612bd683600084900b600a0a63ffffffff612c3016565b9250612c05565b60008260000b1215612c0557612c02836000848103900b600a0a63ffffffff612c8916565b92505b5090919050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b600082612c3f57506000610d73565b82820282848281612c4c57fe5b0414610d705760405162461bcd60e51b8152600401808060200182810382526021815260200180612dd56021913960400191505060405180910390fd5b6000610d7083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183612d525760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d17578181015183820152602001612cff565b50505050905090810190601f168015612d445780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612d5e57fe5b049594505050505056fe6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637443616c6c6572206973206e6f74207468652053747261746567697374206f7220476f7665726e6f7243616c6c6572206973206e6f742074686520476f7665726e6f72000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f7420746865205661756c742c20476f7665726e6f722c206f7220537472617465676973745361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158202d9460819698975a6c9f01af70fc6f240ae6d45252536f47eb9a05cb1514ebb464736f6c634300050b0032", + "solcInputHash": "cca309778b0bcb384ba7e2e97bde53a0", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":false,\"inputs\":[],\"name\":\"unpauseRebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"redeemFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"setTrusteeFeeBps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyAddr\",\"type\":\"address\"}],\"name\":\"harvest\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"transferToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"priceUSDMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"removeStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultBuffer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setTrusteeAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"setPriceProvider\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"approveStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pauseCapital\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"harvest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"supportAsset\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebaseThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyAddr\",\"type\":\"address\"}],\"name\":\"withdrawAllFromStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"setMaxSupplyDiff\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setStrategistAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyFromAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategyToAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_assets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"}],\"name\":\"reallocate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"priceUSDRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxSupplyDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"setVaultBuffer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpauseCapital\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoAllocateThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetDefaultStrategies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setUniswapAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"setAutoAllocateThreshold\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"priceProvider\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"setRebaseThreshold\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"setAssetDefaultStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pauseRebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawAllFromStrategies\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"capitalPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"setRedeemFeeBps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImpl\",\"type\":\"address\"}],\"name\":\"setAdminImpl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"AssetSupported\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"AssetDefaultStrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebasePaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebaseUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"VaultBufferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"RedeemFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"PriceProviderUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"AllocateThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"RebaseThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyDiffChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_yield\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"YieldDistribution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"TrusteeFeeBpsChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"TrusteeAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"approveStrategy(address)\":{\"details\":\"Add a strategy to the Vault.\",\"params\":{\"_addr\":\"Address of the strategy to add\"}},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"harvest()\":{\"details\":\"Collect reward tokens from all strategies and swap for supported stablecoin via Uniswap\"},\"harvest(address)\":{\"details\":\"Collect reward tokens for a specific strategy and swap for supported stablecoin via Uniswap. Called from the vault.\",\"params\":{\"_strategyAddr\":\"Address of the strategy to collect rewards from\"}},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"pauseCapital()\":{\"details\":\"Set the deposit paused flag to true to prevent capital movement.\"},\"pauseRebase()\":{\"details\":\"Set the deposit paused flag to true to prevent rebasing.\"},\"priceUSDMint(address)\":{\"details\":\"Returns the total price in 18 digit USD for a given asset. Never goes above 1, since that is how we price mints\",\"params\":{\"asset\":\"address of the asset\"},\"return\":\"uint256 USD price of 1 of the asset, in 18 decimal fixed\"},\"priceUSDRedeem(address)\":{\"details\":\"Returns the total price in 18 digit USD for a given asset. Never goes below 1, since that is how we price redeems\",\"params\":{\"asset\":\"Addresss of the asset\"},\"return\":\"uint256 USD price of 1 of the asset, in 18 decimal fixed\"},\"reallocate(address,address,address[],uint256[])\":{\"params\":{\"_amounts\":\"Array of amounts of each corresponding asset to move.\",\"_assets\":\"Array of asset address that will be moved\",\"_strategyFromAddress\":\"Address of Strategy to move assets from.\",\"_strategyToAddress\":\"Address of Strategy to move assets to.\"}},\"removeStrategy(address)\":{\"details\":\"Remove a strategy from the Vault. Removes all invested assets and returns them to the Vault.\",\"params\":{\"_addr\":\"Address of the strategy to remove\"}},\"setAdminImpl(address)\":{\"details\":\"set the implementation for the admin, this needs to be in a base class else we cannot set it\",\"params\":{\"newImpl\":\"address of the implementation\"}},\"setAssetDefaultStrategy(address,address)\":{\"details\":\"Set the default Strategy for an asset, i.e. the one which the asset will be automatically allocated to and withdrawn from\",\"params\":{\"_asset\":\"Address of the asset\",\"_strategy\":\"Address of the Strategy\"}},\"setAutoAllocateThreshold(uint256)\":{\"details\":\"Sets the minimum amount of OUSD in a mint to trigger an automatic allocation of funds afterwords.\",\"params\":{\"_threshold\":\"OUSD amount with 18 fixed decimals.\"}},\"setMaxSupplyDiff(uint256)\":{\"details\":\"Sets the maximum allowable difference between total supply and backing assets' value.\"},\"setPriceProvider(address)\":{\"details\":\"Set address of price provider.\",\"params\":{\"_priceProvider\":\"Address of price provider\"}},\"setRebaseThreshold(uint256)\":{\"details\":\"Set a minimum amount of OUSD in a mint or redeem that triggers a rebase\",\"params\":{\"_threshold\":\"OUSD amount with 18 fixed decimals.\"}},\"setRedeemFeeBps(uint256)\":{\"details\":\"Set a fee in basis points to be charged for a redeem.\",\"params\":{\"_redeemFeeBps\":\"Basis point fee to be charged\"}},\"setStrategistAddr(address)\":{\"details\":\"Set address of Strategist\",\"params\":{\"_address\":\"Address of Strategist\"}},\"setTrusteeAddress(address)\":{\"details\":\"Sets the trusteeAddress that can receive a portion of yield. Setting to the zero address disables this feature.\"},\"setTrusteeFeeBps(uint256)\":{\"details\":\"Sets the TrusteeFeeBps to the percentage of yield that should be received in basis points.\"},\"setUniswapAddr(address)\":{\"details\":\"Set address of Uniswap for performing liquidation of strategy reward tokens\",\"params\":{\"_address\":\"Address of Uniswap\"}},\"setVaultBuffer(uint256)\":{\"details\":\"Set a buffer of assets to keep in the Vault to handle most redemptions without needing to spend gas unwinding assets from a Strategy.\",\"params\":{\"_vaultBuffer\":\"Percentage using 18 decimals. 100% = 1e18.\"}},\"supportAsset(address)\":{\"details\":\"Add a supported asset to the contract, i.e. one that can be to mint OUSD.\",\"params\":{\"_asset\":\"Address of asset\"}},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}},\"transferToken(address,uint256)\":{\"details\":\"Transfer token to governor. Intended for recovering tokens stuck in contract, i.e. mistaken sends.\",\"params\":{\"_amount\":\"Amount of the asset to transfer\",\"_asset\":\"Address for the asset\"}},\"unpauseCapital()\":{\"details\":\"Set the deposit paused flag to false to enable capital movement.\"},\"unpauseRebase()\":{\"details\":\"Set the deposit paused flag to true to allow rebasing.\"},\"withdrawAllFromStrategies()\":{\"details\":\"Withdraws all assets from all the strategies and sends assets to the Vault.\"},\"withdrawAllFromStrategy(address)\":{\"details\":\"Withdraws all assets from the strategy and sends assets to the Vault.\",\"params\":{\"_strategyAddr\":\"Strategy address.\"}}}},\"userdoc\":{\"methods\":{\"reallocate(address,address,address[],uint256[])\":{\"notice\":\"Move assets from one Strategy to another\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/vault/VaultAdmin.sol\":\"VaultAdmin\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"@openzeppelin/upgrades/contracts/Initializable.sol\":{\"content\":\"pragma solidity >=0.4.24 <0.7.0;\\n\\n\\n/**\\n * @title Initializable\\n *\\n * @dev Helper contract to support initializer functions. To use it, replace\\n * the constructor with a function that has the `initializer` modifier.\\n * WARNING: Unlike constructors, initializer functions must be manually\\n * invoked. This applies both to deploying an Initializable contract, as well\\n * as extending an Initializable contract via inheritance.\\n * WARNING: When used with inheritance, manual care must be taken to not invoke\\n * a parent initializer twice, or ensure that all initializers are idempotent,\\n * because this is not dealt with automatically as with constructors.\\n */\\ncontract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to use in the initializer function of a contract.\\n */\\n modifier initializer() {\\n require(initializing || isConstructor() || !initialized, \\\"Contract instance has already been initialized\\\");\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function isConstructor() private view returns (bool) {\\n // extcodesize checks the size of the code stored in an address, and\\n // address returns the current address. Since the code is still not\\n // deployed when running a constructor, any checks on its code size will\\n // yield zero, making it an effective way to detect if a contract is\\n // under construction or not.\\n address self = address(this);\\n uint256 cs;\\n assembly { cs := extcodesize(self) }\\n return cs == 0;\\n }\\n\\n // Reserved storage space to allow for layout changes in the future.\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x9bfec92e36234ecc99b5d37230acb6cd1f99560233753162204104a4897e8721\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x01eab42b6d54fa5389598e0663c24680ecc017e2da848e8ea1c40aeaa8225eef\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IOracle {\\n /**\\n * @dev returns the asset price in USD, 8 decimal digits.\\n */\\n function price(address asset) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x7ddbe1f9ed76feb2fbd52ecfe449e17ef67f7edd5616c6a1eda92a84baa1190f\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to platform\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Deposit the entire balance of all supported assets in the Strategy\\n * to the platform\\n */\\n function depositAll() external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardToken() external;\\n\\n /**\\n * @dev The address of the reward token for the Strategy.\\n */\\n function rewardTokenAddress() external pure returns (address);\\n\\n /**\\n * @dev The threshold (denominated in the reward token) over which the\\n * vault will auto harvest on allocate calls.\\n */\\n function rewardLiquidationThreshold() external pure returns (uint256);\\n}\\n\",\"keccak256\":\"0xe03dc1c97ad3677296da9a7e1e5f708abd227d1147f6f220c5cc8f23c1cd87e0\"},\"contracts/interfaces/uniswap/IUniswapV2Router02.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IUniswapV2Router {\\n function WETH() external pure returns (address);\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address[] calldata path,\\n address to,\\n uint256 deadline\\n ) external returns (uint256[] memory amounts);\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n );\\n}\\n\",\"keccak256\":\"0x33943cfab99996faa745df3c21b95b3ed49783b4c3392e4c71e25f6712af509b\"},\"contracts/token/OUSD.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {\\n InitializableERC20Detailed\\n} from \\\"../utils/InitializableERC20Detailed.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\n/**\\n * NOTE that this is an ERC20 token but the invariant that the sum of\\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\\n * rebasing design. Any integrations with OUSD should be aware.\\n */\\n\\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n\\n event TotalSupplyUpdated(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n\\n enum RebaseOptions { NotSet, OptOut, OptIn }\\n\\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\\n uint256 public _totalSupply;\\n mapping(address => mapping(address => uint256)) private _allowances;\\n address public vaultAddress = address(0);\\n mapping(address => uint256) private _creditBalances;\\n uint256 public rebasingCredits;\\n uint256 public rebasingCreditsPerToken;\\n // Frozen address/credits are non rebasing (value is held in contracts which\\n // do not receive yield unless they explicitly opt in)\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) public nonRebasingCreditsPerToken;\\n mapping(address => RebaseOptions) public rebaseState;\\n\\n function initialize(\\n string calldata _nameArg,\\n string calldata _symbolArg,\\n address _vaultAddress\\n ) external onlyGovernor initializer {\\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\\n rebasingCreditsPerToken = 1e18;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Savings Manager contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return The total supply of OUSD.\\n */\\n function totalSupply() public view returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the _amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n if (_creditBalances[_account] == 0) return 0;\\n return\\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n return (_creditBalances[_account], _creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the _amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(\\n _value <= balanceOf(msg.sender),\\n \\\"Transfer greater than balance\\\"\\n );\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The _amount of tokens to be transferred.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(_value <= balanceOf(_from), \\\"Transfer greater than balance\\\");\\n\\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\\n _value\\n );\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Update the count of non rebasing credits in response to a transfer\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value Amount of OUSD to transfer\\n */\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\\n\\n // Credits deducted and credited might be different due to the\\n // differing creditsPerToken used by each account\\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\\n\\n _creditBalances[_from] = _creditBalances[_from].sub(\\n creditsDeducted,\\n \\\"Transfer amount exceeds balance\\\"\\n );\\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\\n\\n if (isNonRebasingTo && !isNonRebasingFrom) {\\n // Transfer to non-rebasing account from rebasing account, credits\\n // are removed from the non rebasing tally\\n nonRebasingSupply = nonRebasingSupply.add(_value);\\n // Update rebasingCredits by subtracting the deducted amount\\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\\n // Transfer to rebasing account from non-rebasing account\\n // Decreasing non-rebasing credits by the amount that was sent\\n nonRebasingSupply = nonRebasingSupply.sub(_value);\\n // Update rebasingCredits by adding the credited amount\\n rebasingCredits = rebasingCredits.add(creditsCredited);\\n }\\n }\\n\\n /**\\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n public\\n view\\n returns (uint256)\\n {\\n return _allowances[_owner][_spender];\\n }\\n\\n /**\\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\\n * msg.sender. This method is included for ERC20 compatibility.\\n * increaseAllowance and decreaseAllowance should be used instead.\\n * Changing an allowance with this method brings the risk that someone may transfer both\\n * the old and the new allowance - if they are both greater than zero - if a transfer\\n * transaction is mined before the later approve() call is mined.\\n *\\n * @param _spender The address which will spend the funds.\\n * @param _value The _amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) public returns (bool) {\\n _allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\\n * This method should be used instead of approve() to avoid the double approval vulnerability\\n * described above.\\n * @param _spender The address which will spend the funds.\\n * @param _addedValue The _amount of tokens to increase the allowance by.\\n */\\n function increaseAllowance(address _spender, uint256 _addedValue)\\n public\\n returns (bool)\\n {\\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\\n .add(_addedValue);\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\\n * @param _spender The address which will spend the funds.\\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\\n */\\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\\n public\\n returns (bool)\\n {\\n uint256 oldValue = _allowances[msg.sender][_spender];\\n if (_subtractedValue >= oldValue) {\\n _allowances[msg.sender][_spender] = 0;\\n } else {\\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\\n }\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Mints new tokens, increasing totalSupply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n _mint(_account, _amount);\\n }\\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 * - `to` cannot be the zero address.\\n */\\n function _mint(address _account, uint256 _amount) internal nonReentrant {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\\n\\n // If the account is non rebasing and doesn't have a set creditsPerToken\\n // then set it i.e. this is a mint from a fresh contract\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.add(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.add(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.add(_amount);\\n\\n require(_totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @dev Burns tokens, decreasing totalSupply.\\n */\\n function burn(address account, uint256 amount) external onlyVault {\\n _burn(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 nonReentrant {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n uint256 currentCredits = _creditBalances[_account];\\n\\n // Remove the credits, burning rounding errors\\n if (\\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\\n ) {\\n // Handle dust from rounding\\n _creditBalances[_account] = 0;\\n } else if (currentCredits > creditAmount) {\\n _creditBalances[_account] = _creditBalances[_account].sub(\\n creditAmount\\n );\\n } else {\\n revert(\\\"Remove exceeds balance\\\");\\n }\\n\\n // Remove from the credit tallies and non-rebasing supply\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.sub(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.sub(_amount);\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n if (nonRebasingCreditsPerToken[_account] != 0) {\\n return nonRebasingCreditsPerToken[_account];\\n } else {\\n return rebasingCreditsPerToken;\\n }\\n }\\n\\n /**\\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\\n * Also, ensure contracts are non-rebasing if they have not opted in.\\n * @param _account Address of the account.\\n */\\n function _isNonRebasingAccount(address _account) internal returns (bool) {\\n bool isContract = Address.isContract(_account);\\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\\n _ensureRebasingMigration(_account);\\n }\\n return nonRebasingCreditsPerToken[_account] > 0;\\n }\\n\\n /**\\n * @dev Ensures internal account for rebasing and non-rebasing credits and\\n * supply is updated following deployment of frozen yield change.\\n */\\n function _ensureRebasingMigration(address _account) internal {\\n if (nonRebasingCreditsPerToken[_account] == 0) {\\n // Set fixed credits per token for this account\\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\\n // Update non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\\n // Update credit tallies\\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\\n }\\n }\\n\\n /**\\n * @dev Add a contract address to the non rebasing exception list. I.e. the\\n * address's balance will be part of rebases so the account will be exposed\\n * to upside and downside.\\n */\\n function rebaseOptIn() public nonReentrant {\\n require(_isNonRebasingAccount(msg.sender), \\\"Account has not opted out\\\");\\n\\n // Convert balance into the same amount at the current exchange rate\\n uint256 newCreditBalance = _creditBalances[msg.sender]\\n .mul(rebasingCreditsPerToken)\\n .div(_creditsPerToken(msg.sender));\\n\\n // Decreasing non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\\n\\n _creditBalances[msg.sender] = newCreditBalance;\\n\\n // Increase rebasing credits, totalSupply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\\n\\n rebaseState[msg.sender] = RebaseOptions.OptIn;\\n\\n // Delete any fixed credits per token\\n delete nonRebasingCreditsPerToken[msg.sender];\\n }\\n\\n /**\\n * @dev Remove a contract address to the non rebasing exception list.\\n */\\n function rebaseOptOut() public nonReentrant {\\n require(!_isNonRebasingAccount(msg.sender), \\\"Account has not opted in\\\");\\n\\n // Increase non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\\n // Set fixed credits per token\\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\\n\\n // Decrease rebasing credits, total supply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\\n\\n // Mark explicitly opted out of rebasing\\n rebaseState[msg.sender] = RebaseOptions.OptOut;\\n }\\n\\n /**\\n * @dev Modify the supply without minting new tokens. This uses a change in\\n * the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n * @return uint256 representing the new total supply.\\n */\\n function changeSupply(uint256 _newTotalSupply)\\n external\\n onlyVault\\n nonReentrant\\n {\\n require(_totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (_totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n return;\\n }\\n\\n _totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\\n _totalSupply.sub(nonRebasingSupply)\\n );\\n\\n require(rebasingCreditsPerToken > 0, \\\"Invalid change in supply\\\");\\n\\n _totalSupply = rebasingCredits\\n .divPrecisely(rebasingCreditsPerToken)\\n .add(nonRebasingSupply);\\n\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n }\\n}\\n\",\"keccak256\":\"0xea89a8b152b363982ba8db340b1e20c3194b2e75a06630cbbf43e3c50fff61a4\"},\"contracts/utils/Helpers.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0xd2ca92e0af883dc1aec5b22caced274e59829e0e30a9e955dcc48b8d921f5cdc\"},\"contracts/utils/InitializableERC20Detailed.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/**\\n * @dev Optional functions from the ERC20 standard.\\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\\n */\\ncontract InitializableERC20Detailed is IERC20 {\\n // Storage gap to skip storage from prior to OUSD reset\\n uint256[100] private _____gap;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\\n * these values are immutable: they can only be set once during\\n * construction.\\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\\n */\\n function _initialize(\\n string memory nameArg,\\n string memory symbolArg,\\n uint8 decimalsArg\\n ) internal {\\n _name = nameArg;\\n _symbol = symbolArg;\\n _decimals = decimalsArg;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view 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 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.\\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 returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x7919369d0f3bd74b4f0ee78a682afe43f91b186cdd0708e303068e4feeb29007\"},\"contracts/utils/StableMath.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n// Based on StableMath from Stability Labs Pty. Ltd.\\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\\n\\nlibrary StableMath {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Scaling unit for use in specific calculations,\\n * where 1 * 10**18, or 1e18 represents a unit '1'\\n */\\n uint256 private constant FULL_SCALE = 1e18;\\n\\n /***************************************\\n Helpers\\n ****************************************/\\n\\n /**\\n * @dev Adjust the scale of an integer\\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\\n */\\n function scaleBy(uint256 x, int8 adjustment)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (adjustment > 0) {\\n x = x.mul(10**uint256(adjustment));\\n } else if (adjustment < 0) {\\n x = x.div(10**uint256(adjustment * -1));\\n }\\n return x;\\n }\\n\\n /***************************************\\n Precise Arithmetic\\n ****************************************/\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\\n return mulTruncateScale(x, y, FULL_SCALE);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @param scale Scale unit\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncateScale(\\n uint256 x,\\n uint256 y,\\n uint256 scale\\n ) internal pure returns (uint256) {\\n // e.g. assume scale = fullScale\\n // z = 10e18 * 9e17 = 9e36\\n uint256 z = x.mul(y);\\n // return 9e38 / 1e18 = 9e18\\n return z.div(scale);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit, rounded up to the closest base unit.\\n */\\n function mulTruncateCeil(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e17 * 17268172638 = 138145381104e17\\n uint256 scaled = x.mul(y);\\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\\n return ceil.div(FULL_SCALE);\\n }\\n\\n /**\\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\\n * @param x Left hand input to division\\n * @param y Right hand input to division\\n * @return Result after multiplying the left operand by the scale, and\\n * executing the division on the right hand input.\\n */\\n function divPrecisely(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e18 * 1e18 = 8e36\\n uint256 z = x.mul(FULL_SCALE);\\n // e.g. 8e36 / 10e18 = 8e17\\n return z.div(y);\\n }\\n}\\n\",\"keccak256\":\"0xa77fccf850feb6d54ba3a6530f92554caef8a67a1ceb573d4f8a5d1bf64ff9d2\"},\"contracts/vault/VaultAdmin.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Vault Admin Contract\\n * @notice The VaultAdmin contract makes configuration and admin calls on the vault.\\n * @author Origin Protocol Inc\\n */\\n\\nimport \\\"./VaultStorage.sol\\\";\\nimport { IOracle } from \\\"../interfaces/IOracle.sol\\\";\\nimport { IUniswapV2Router } from \\\"../interfaces/uniswap/IUniswapV2Router02.sol\\\";\\n\\ncontract VaultAdmin is VaultStorage {\\n /**\\n * @dev Verifies that the caller is the Vault, Governor, or Strategist.\\n */\\n modifier onlyVaultOrGovernorOrStrategist() {\\n require(\\n msg.sender == address(this) ||\\n msg.sender == strategistAddr ||\\n isGovernor(),\\n \\\"Caller is not the Vault, Governor, or Strategist\\\"\\n );\\n _;\\n }\\n\\n modifier onlyGovernorOrStrategist() {\\n require(\\n msg.sender == strategistAddr || isGovernor(),\\n \\\"Caller is not the Strategist or Governor\\\"\\n );\\n _;\\n }\\n\\n /***************************************\\n Configuration\\n ****************************************/\\n\\n /**\\n * @dev Set address of price provider.\\n * @param _priceProvider Address of price provider\\n */\\n function setPriceProvider(address _priceProvider) external onlyGovernor {\\n priceProvider = _priceProvider;\\n emit PriceProviderUpdated(_priceProvider);\\n }\\n\\n /**\\n * @dev Set a fee in basis points to be charged for a redeem.\\n * @param _redeemFeeBps Basis point fee to be charged\\n */\\n function setRedeemFeeBps(uint256 _redeemFeeBps) external onlyGovernor {\\n redeemFeeBps = _redeemFeeBps;\\n emit RedeemFeeUpdated(_redeemFeeBps);\\n }\\n\\n /**\\n * @dev Set a buffer of assets to keep in the Vault to handle most\\n * redemptions without needing to spend gas unwinding assets from a Strategy.\\n * @param _vaultBuffer Percentage using 18 decimals. 100% = 1e18.\\n */\\n function setVaultBuffer(uint256 _vaultBuffer)\\n external\\n onlyGovernorOrStrategist\\n {\\n require(_vaultBuffer <= 1e18, \\\"Invalid value\\\");\\n vaultBuffer = _vaultBuffer;\\n emit VaultBufferUpdated(_vaultBuffer);\\n }\\n\\n /**\\n * @dev Sets the minimum amount of OUSD in a mint to trigger an\\n * automatic allocation of funds afterwords.\\n * @param _threshold OUSD amount with 18 fixed decimals.\\n */\\n function setAutoAllocateThreshold(uint256 _threshold)\\n external\\n onlyGovernor\\n {\\n autoAllocateThreshold = _threshold;\\n emit AllocateThresholdUpdated(_threshold);\\n }\\n\\n /**\\n * @dev Set a minimum amount of OUSD in a mint or redeem that triggers a\\n * rebase\\n * @param _threshold OUSD amount with 18 fixed decimals.\\n */\\n function setRebaseThreshold(uint256 _threshold) external onlyGovernor {\\n rebaseThreshold = _threshold;\\n emit RebaseThresholdUpdated(_threshold);\\n }\\n\\n /**\\n * @dev Set address of Uniswap for performing liquidation of strategy reward\\n * tokens\\n * @param _address Address of Uniswap\\n */\\n function setUniswapAddr(address _address) external onlyGovernor {\\n uniswapAddr = _address;\\n emit UniswapUpdated(_address);\\n }\\n\\n /**\\n * @dev Set address of Strategist\\n * @param _address Address of Strategist\\n */\\n function setStrategistAddr(address _address) external onlyGovernor {\\n strategistAddr = _address;\\n emit StrategistUpdated(_address);\\n }\\n\\n /**\\n * @dev Set the default Strategy for an asset, i.e. the one which the asset\\n will be automatically allocated to and withdrawn from\\n * @param _asset Address of the asset\\n * @param _strategy Address of the Strategy\\n */\\n function setAssetDefaultStrategy(address _asset, address _strategy)\\n external\\n onlyGovernorOrStrategist\\n {\\n emit AssetDefaultStrategyUpdated(_asset, _strategy);\\n require(strategies[_strategy].isSupported, \\\"Strategy not approved\\\");\\n IStrategy strategy = IStrategy(_strategy);\\n require(assets[_asset].isSupported, \\\"Asset is not supported\\\");\\n require(\\n strategy.supportsAsset(_asset),\\n \\\"Asset not supported by Strategy\\\"\\n );\\n assetDefaultStrategies[_asset] = _strategy;\\n }\\n\\n /**\\n * @dev Add a supported asset to the contract, i.e. one that can be\\n * to mint OUSD.\\n * @param _asset Address of asset\\n */\\n function supportAsset(address _asset) external onlyGovernor {\\n require(!assets[_asset].isSupported, \\\"Asset already supported\\\");\\n\\n assets[_asset] = Asset({ isSupported: true });\\n allAssets.push(_asset);\\n\\n // Verify that our oracle supports the asset\\n // slither-disable-next-line unused-return\\n IOracle(priceProvider).price(_asset);\\n\\n emit AssetSupported(_asset);\\n }\\n\\n /**\\n * @dev Add a strategy to the Vault.\\n * @param _addr Address of the strategy to add\\n */\\n function approveStrategy(address _addr) external onlyGovernor {\\n require(!strategies[_addr].isSupported, \\\"Strategy already approved\\\");\\n strategies[_addr] = Strategy({ isSupported: true, _deprecated: 0 });\\n allStrategies.push(_addr);\\n emit StrategyApproved(_addr);\\n }\\n\\n /**\\n * @dev Remove a strategy from the Vault. Removes all invested assets and\\n * returns them to the Vault.\\n * @param _addr Address of the strategy to remove\\n */\\n\\n function removeStrategy(address _addr) external onlyGovernor {\\n require(strategies[_addr].isSupported, \\\"Strategy not approved\\\");\\n\\n // Initialize strategyIndex with out of bounds result so function will\\n // revert if no valid index found\\n uint256 strategyIndex = allStrategies.length;\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n if (allStrategies[i] == _addr) {\\n strategyIndex = i;\\n break;\\n }\\n }\\n\\n if (strategyIndex < allStrategies.length) {\\n allStrategies[strategyIndex] = allStrategies[allStrategies.length -\\n 1];\\n allStrategies.pop();\\n\\n // Withdraw all assets\\n IStrategy strategy = IStrategy(_addr);\\n strategy.withdrawAll();\\n // Call harvest after withdraw in case withdraw triggers\\n // distribution of additional reward tokens (true for Compound)\\n _harvest(_addr);\\n emit StrategyRemoved(_addr);\\n }\\n\\n // Clean up struct in mapping, this can be removed later\\n // See https://github.com/OriginProtocol/origin-dollar/issues/324\\n strategies[_addr].isSupported = false;\\n }\\n\\n /**\\n * @notice Move assets from one Strategy to another\\n * @param _strategyFromAddress Address of Strategy to move assets from.\\n * @param _strategyToAddress Address of Strategy to move assets to.\\n * @param _assets Array of asset address that will be moved\\n * @param _amounts Array of amounts of each corresponding asset to move.\\n */\\n function reallocate(\\n address _strategyFromAddress,\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external onlyGovernorOrStrategist {\\n require(\\n strategies[_strategyFromAddress].isSupported,\\n \\\"Invalid from Strategy\\\"\\n );\\n require(\\n strategies[_strategyToAddress].isSupported,\\n \\\"Invalid to Strategy\\\"\\n );\\n require(_assets.length == _amounts.length, \\\"Parameter length mismatch\\\");\\n\\n IStrategy strategyFrom = IStrategy(_strategyFromAddress);\\n IStrategy strategyTo = IStrategy(_strategyToAddress);\\n\\n for (uint256 i = 0; i < _assets.length; i++) {\\n require(strategyTo.supportsAsset(_assets[i]), \\\"Asset unsupported\\\");\\n // Withdraw from Strategy and pass other Strategy as recipient\\n strategyFrom.withdraw(address(strategyTo), _assets[i], _amounts[i]);\\n }\\n // Tell new Strategy to deposit into protocol\\n strategyTo.depositAll();\\n }\\n\\n /**\\n * @dev Sets the maximum allowable difference between\\n * total supply and backing assets' value.\\n */\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor {\\n maxSupplyDiff = _maxSupplyDiff;\\n emit MaxSupplyDiffChanged(_maxSupplyDiff);\\n }\\n\\n /**\\n * @dev Sets the trusteeAddress that can receive a portion of yield.\\n * Setting to the zero address disables this feature.\\n */\\n function setTrusteeAddress(address _address) external onlyGovernor {\\n trusteeAddress = _address;\\n emit TrusteeAddressChanged(_address);\\n }\\n\\n /**\\n * @dev Sets the TrusteeFeeBps to the percentage of yield that should be\\n * received in basis points.\\n */\\n function setTrusteeFeeBps(uint256 _basis) external onlyGovernor {\\n require(_basis <= 5000, \\\"basis cannot exceed 50%\\\");\\n trusteeFeeBps = _basis;\\n emit TrusteeFeeBpsChanged(_basis);\\n }\\n\\n /***************************************\\n Pause\\n ****************************************/\\n\\n /**\\n * @dev Set the deposit paused flag to true to prevent rebasing.\\n */\\n function pauseRebase() external onlyGovernorOrStrategist {\\n rebasePaused = true;\\n emit RebasePaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to true to allow rebasing.\\n */\\n function unpauseRebase() external onlyGovernor {\\n rebasePaused = false;\\n emit RebaseUnpaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to true to prevent capital movement.\\n */\\n function pauseCapital() external onlyGovernorOrStrategist {\\n capitalPaused = true;\\n emit CapitalPaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to false to enable capital movement.\\n */\\n function unpauseCapital() external onlyGovernorOrStrategist {\\n capitalPaused = false;\\n emit CapitalUnpaused();\\n }\\n\\n /***************************************\\n Rewards\\n ****************************************/\\n\\n /**\\n * @dev Transfer token to governor. Intended for recovering tokens stuck in\\n * contract, i.e. mistaken sends.\\n * @param _asset Address for the asset\\n * @param _amount Amount of the asset to transfer\\n */\\n function transferToken(address _asset, uint256 _amount)\\n external\\n onlyGovernor\\n {\\n require(!assets[_asset].isSupported, \\\"Only unsupported assets\\\");\\n IERC20(_asset).safeTransfer(governor(), _amount);\\n }\\n\\n /**\\n * @dev Collect reward tokens from all strategies and swap for supported\\n * stablecoin via Uniswap\\n */\\n function harvest() external onlyGovernorOrStrategist {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n _harvest(allStrategies[i]);\\n }\\n }\\n\\n /**\\n * @dev Collect reward tokens for a specific strategy and swap for supported\\n * stablecoin via Uniswap. Called from the vault.\\n * @param _strategyAddr Address of the strategy to collect rewards from\\n */\\n function harvest(address _strategyAddr)\\n external\\n onlyVaultOrGovernorOrStrategist\\n returns (uint256[] memory)\\n {\\n return _harvest(_strategyAddr);\\n }\\n\\n /**\\n * @dev Collect reward tokens from a single strategy and swap them for a\\n * supported stablecoin via Uniswap\\n * @param _strategyAddr Address of the strategy to collect rewards from\\n */\\n function _harvest(address _strategyAddr)\\n internal\\n returns (uint256[] memory)\\n {\\n IStrategy strategy = IStrategy(_strategyAddr);\\n address rewardTokenAddress = strategy.rewardTokenAddress();\\n if (rewardTokenAddress != address(0)) {\\n strategy.collectRewardToken();\\n\\n if (uniswapAddr != address(0)) {\\n IERC20 rewardToken = IERC20(strategy.rewardTokenAddress());\\n uint256 rewardTokenAmount = rewardToken.balanceOf(\\n address(this)\\n );\\n if (rewardTokenAmount > 0) {\\n // Give Uniswap full amount allowance\\n rewardToken.safeApprove(uniswapAddr, 0);\\n rewardToken.safeApprove(uniswapAddr, rewardTokenAmount);\\n\\n // Uniswap redemption path\\n address[] memory path = new address[](3);\\n path[0] = strategy.rewardTokenAddress();\\n path[1] = IUniswapV2Router(uniswapAddr).WETH();\\n path[2] = allAssets[1]; // USDT\\n\\n return\\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\\n rewardTokenAmount,\\n uint256(0),\\n path,\\n address(this),\\n now.add(1800)\\n );\\n }\\n }\\n }\\n }\\n\\n /***************************************\\n Pricing\\n ****************************************/\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Never goes above 1, since that is how we price mints\\n * @param asset address of the asset\\n * @return uint256 USD price of 1 of the asset, in 18 decimal fixed\\n */\\n function priceUSDMint(address asset) external view returns (uint256) {\\n uint256 price = IOracle(priceProvider).price(asset);\\n if (price > 1e8) {\\n price = 1e8;\\n }\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return price.scaleBy(10);\\n }\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Never goes below 1, since that is how we price redeems\\n * @param asset Addresss of the asset\\n * @return uint256 USD price of 1 of the asset, in 18 decimal fixed\\n */\\n function priceUSDRedeem(address asset) external view returns (uint256) {\\n uint256 price = IOracle(priceProvider).price(asset);\\n if (price < 1e8) {\\n price = 1e8;\\n }\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return price.scaleBy(10);\\n }\\n\\n /***************************************\\n Strategies Admin\\n ****************************************/\\n\\n /**\\n * @dev Withdraws all assets from the strategy and sends assets to the Vault.\\n * @param _strategyAddr Strategy address.\\n */\\n function withdrawAllFromStrategy(address _strategyAddr)\\n external\\n onlyGovernorOrStrategist\\n {\\n require(\\n strategies[_strategyAddr].isSupported,\\n \\\"Strategy is not supported\\\"\\n );\\n IStrategy strategy = IStrategy(_strategyAddr);\\n strategy.withdrawAll();\\n }\\n\\n /**\\n * @dev Withdraws all assets from all the strategies and sends assets to the Vault.\\n */\\n function withdrawAllFromStrategies() external onlyGovernorOrStrategist {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n strategy.withdrawAll();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x64bfef426714450ca65e03819bcf4baef47eb20cd882456bbc5cd586b4ee45f0\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD VaultStorage Contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\n\\ncontract VaultStorage is Initializable, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n using SafeMath for int256;\\n using SafeERC20 for IERC20;\\n\\n event AssetSupported(address _asset);\\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\\n event PriceProviderUpdated(address _priceProvider);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event UniswapUpdated(address _address);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n\\n // Assets supported by the Vault, i.e. Stablecoins\\n struct Asset {\\n bool isSupported;\\n }\\n mapping(address => Asset) assets;\\n address[] allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n mapping(address => Strategy) strategies;\\n address[] allStrategies;\\n\\n // Address of the Oracle price provider contract\\n address public priceProvider;\\n // Pausing bools\\n bool public rebasePaused = false;\\n bool public capitalPaused = true;\\n // Redemption fee in basis points\\n uint256 public redeemFeeBps;\\n // Buffer of assets to keep in Vault to handle (most) withdrawals\\n uint256 public vaultBuffer;\\n // Mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n // Mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n OUSD oUSD;\\n\\n //keccak256(\\\"OUSD.vault.governor.admin.impl\\\");\\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\\n\\n // Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n // Address of Uniswap\\n address public uniswapAddr = address(0);\\n\\n // Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n // Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n mapping(address => address) public assetDefaultStrategies;\\n\\n uint256 public maxSupplyDiff;\\n\\n // Trustee contract that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n // Amount of yield collected in basis points\\n uint256 public trusteeFeeBps;\\n\\n /**\\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\\n * @param newImpl address of the implementation\\n */\\n function setAdminImpl(address newImpl) external onlyGovernor {\\n require(\\n Address.isContract(newImpl),\\n \\\"new implementation is not a contract\\\"\\n );\\n bytes32 position = adminImplPosition;\\n assembly {\\n sstore(position, newImpl)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc945fa95b0fb31ae523cf91bd89bbf1289de38b02a8b082b98fed152c00c7746\"}},\"version\":1}", + "bytecode": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b6000805160206200319f83398151915255565b6000805160206200319f8339815191525490565b6130ad80620000f26000396000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80635d36b19011610151578063b2c9336d116100c3578063c7af335211610087578063c7af33521461072b578063c991911214610733578063d38bfff41461073b578063e6cc543214610761578063eb03654b14610769578063fc0cfeee1461078657610274565b8063b2c9336d146106b3578063b888879e146106d0578063b890ebf6146106d8578063bc90106b146106f5578063c5f008411461072357610274565b80638e510b52116101155780638e510b52146106325780638ec489a21461063a57806394828ffd146106575780639fa1826e1461065f578063a403e4d514610667578063aea173d51461068d57610274565b80635d36b190146104e6578063663e64ce146104ee578063773540b31461050b5780637fe2d393146105315780638c5cbb891461060c57610274565b80632da845a8116101ea57806349c1d54d116101ae57806349c1d54d146104665780634cd55c2d1461046e57806352d38e5d1461049457806353ca9f241461049c578063570d8e1d146104b8578063597c8910146104c057610274565b80632da845a8146103e4578063372aa2241461040a5780633b8ae397146104305780633dbc911f146104565780634641257d1461045e57610274565b80631072cbea1161023c5780631072cbea1461035457806310d3fdac14610380578063128a8b05146103a6578063175188e8146103ae5780631edfe3da146103d4578063207134b0146103dc57610274565b806309f49bf51461027957806309f6442c146102835780630acbda751461029d5780630c340a24146102ba5780630e5c011e146102de575b600080fd5b6102816107ac565b005b61028b61082b565b60408051918252519081900360200190f35b610281600480360360208110156102b357600080fd5b5035610831565b6102c261090a565b604080516001600160a01b039092168252519081900360200190f35b610304600480360360208110156102f457600080fd5b50356001600160a01b0316610919565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610340578181015183820152602001610328565b505050509050019250505060405180910390f35b6102816004803603604081101561036a57600080fd5b506001600160a01b03813516906020013561098d565b61028b6004803603602081101561039657600080fd5b50356001600160a01b0316610a68565b6102c2610b10565b610281600480360360208110156103c457600080fd5b50356001600160a01b0316610b1f565b61028b610d83565b61028b610d89565b610281600480360360208110156103fa57600080fd5b50356001600160a01b0316610d8f565b6102816004803603602081101561042057600080fd5b50356001600160a01b0316610e2a565b6102816004803603602081101561044657600080fd5b50356001600160a01b0316610ec5565b610281611032565b6102816110c7565b6102c2611161565b6102816004803603602081101561048457600080fd5b50356001600160a01b0316611170565b61028b611344565b6104a461134a565b604080519115158252519081900360200190f35b6102c261135a565b610281600480360360208110156104d657600080fd5b50356001600160a01b0316611369565b610281611489565b6102816004803603602081101561050457600080fd5b50356114eb565b6102816004803603602081101561052157600080fd5b50356001600160a01b031661156d565b6102816004803603608081101561054757600080fd5b6001600160a01b03823581169260208101359091169181019060608101604082013564010000000081111561057b57600080fd5b82018360208201111561058d57600080fd5b803590602001918460208302840111640100000000831117156105af57600080fd5b9193909290916020810190356401000000008111156105cd57600080fd5b8201836020820111156105df57600080fd5b8035906020019184602083028401116401000000008311171561060157600080fd5b509092509050611608565b61028b6004803603602081101561062257600080fd5b50356001600160a01b0316611993565b61028b611a33565b6102816004803603602081101561065057600080fd5b5035611a39565b610281611b18565b61028b611ba7565b6102c26004803603602081101561067d57600080fd5b50356001600160a01b0316611bad565b610281600480360360208110156106a357600080fd5b50356001600160a01b0316611bc8565b610281600480360360208110156106c957600080fd5b5035611c63565b6102c2611ce5565b610281600480360360208110156106ee57600080fd5b5035611cf4565b6102816004803603604081101561070b57600080fd5b506001600160a01b0381358116916020013516611d76565b610281611fe1565b6104a4612076565b610281612099565b6102816004803603602081101561075157600080fd5b50356001600160a01b031661217c565b6104a4612216565b6102816004803603602081101561077f57600080fd5b5035612226565b6102816004803603602081101561079c57600080fd5b50356001600160a01b03166122a8565b6107b4612076565b6107f3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6037805460ff60a01b191690556040517fbc044409505c95b6b851433df96e1beae715c909d8e7c1d6d7ab783300d4e3b990600090a1565b60385481565b610839612076565b610878576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6113888111156108cf576040805162461bcd60e51b815260206004820152601760248201527f62617369732063616e6e6f742065786365656420353025000000000000000000604482015290519081900360640190fd5b60438190556040805182815290517f56287a45051933ea374811b3d5d165033047be5572cac676f7c28b8be4f746c79181900360200190a150565b6000610914612357565b905090565b6060333014806109335750603f546001600160a01b031633145b806109415750610941612076565b61097c5760405162461bcd60e51b8152600401808060200182810382526030815260200180612fb96030913960400191505060405180910390fd5b6109858261237c565b90505b919050565b610995612076565b6109d4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526033602052604090205460ff1615610a42576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c7920756e737570706f7274656420617373657473000000000000000000604482015290519081900360640190fd5b610a64610a4d61090a565b6001600160a01b038416908363ffffffff6128bc16565b5050565b603754604080516315d5220f60e31b81526001600160a01b03848116600483015291516000938493169163aea91078916024808301926020929190829003018186803b158015610ab757600080fd5b505afa158015610acb573d6000803e3d6000fd5b505050506040513d6020811015610ae157600080fd5b505190506305f5e100811115610af857506305f5e1005b610b0981600a63ffffffff61291316565b9392505050565b603e546001600160a01b031681565b610b27612076565b610b66576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff16610bcb576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b60365460005b603654811015610c1d57826001600160a01b031660368281548110610bf257fe5b6000918252602090912001546001600160a01b03161415610c1557809150610c1d565b600101610bd1565b50603654811015610d6157603680546000198101908110610c3a57fe5b600091825260209091200154603680546001600160a01b039092169183908110610c6057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506036805480610c9957fe5b6001900381819060005260206000200160006101000a8154906001600160a01b03021916905590556000829050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d0157600080fd5b505af1158015610d15573d6000803e3d6000fd5b50505050610d228361237c565b50604080516001600160a01b038516815290517f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea49181900360200190a1505b506001600160a01b03166000908152603560205260409020805460ff19169055565b60395481565b60435481565b610d97612076565b610dd6576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1e4af5ac389e8cde1bdaa6830881b6c987c62a45cfb3b33d27d805cde3b577509181900360200190a150565b610e32612076565b610e71576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603780546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb266add5f3044b17d27db796af992cecbe413921b4e8aaaee03c719e16b9806a9181900360200190a150565b610ecd612076565b610f0c576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff1615610f7a576040805162461bcd60e51b815260206004820152601960248201527f537472617465677920616c726561647920617070726f76656400000000000000604482015290519081900360640190fd5b6040805180820182526001808252600060208084018281526001600160a01b038716808452603583528684209551865460ff19169015151786559051948401949094556036805493840181559091527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890910180546001600160a01b03191683179055825191825291517f960dd94cbb79169f09a4e445d58b895df2d9bffa5b31055d0932d801724a20d1929181900390910190a150565b603f546001600160a01b031633148061104e575061104e612076565b6110895760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a81b1916600160a81b1790556040517f71f0e5b62f846a22e0b4d159e516e62fa9c2b8eb570be15f83e67d98a2ee51e090600090a1565b603f546001600160a01b03163314806110e357506110e3612076565b61111e5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b60005b60365481101561115e576111556036828154811061113b57fe5b6000918252602090912001546001600160a01b031661237c565b50600101611121565b50565b6042546001600160a01b031681565b611178612076565b6111b7576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526033602052604090205460ff1615611225576040805162461bcd60e51b815260206004820152601760248201527f417373657420616c726561647920737570706f72746564000000000000000000604482015290519081900360640190fd5b604080516020808201835260018083526001600160a01b038581166000818152603385528681209551865460ff1916901515179095556034805493840181559094527f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c190910180546001600160a01b0319168417905560375484516315d5220f60e31b81526004810194909452935193169263aea91078926024808201939291829003018186803b1580156112d957600080fd5b505afa1580156112ed573d6000803e3d6000fd5b505050506040513d602081101561130357600080fd5b5050604080516001600160a01b038316815290517f4f1ac48525e50059cc1cc6e0e1940ece0dd653a4db4841538d6aef036be2fb7b9181900360200190a150565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b603f546001600160a01b03163314806113855750611385612076565b6113c05760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6001600160a01b03811660009081526035602052604090205460ff1661142d576040805162461bcd60e51b815260206004820152601960248201527f5374726174656779206973206e6f7420737570706f7274656400000000000000604482015290519081900360640190fd5b6000819050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561146d57600080fd5b505af1158015611481573d6000803e3d6000fd5b505050505050565b61149161296f565b6001600160a01b0316336001600160a01b0316146114e05760405162461bcd60e51b81526004018080602001828103825260308152602001806130496030913960400191505060405180910390fd5b6114e933612994565b565b6114f3612076565b611532576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b60418190556040805182815290517f95201f9c21f26877223b1ff4073936a6484c35495649e60e55730497aeb60d939181900360200190a150565b611575612076565b6115b4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603f80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee9181900360200190a150565b603f546001600160a01b03163314806116245750611624612076565b61165f5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6001600160a01b03861660009081526035602052604090205460ff166116c4576040805162461bcd60e51b8152602060048201526015602482015274496e76616c69642066726f6d20537472617465677960581b604482015290519081900360640190fd5b6001600160a01b03851660009081526035602052604090205460ff16611727576040805162461bcd60e51b8152602060048201526013602482015272496e76616c696420746f20537472617465677960681b604482015290519081900360640190fd5b82811461177b576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b858560005b8581101561193557816001600160a01b031663aa388af68888848181106117a357fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156117f957600080fd5b505afa15801561180d573d6000803e3d6000fd5b505050506040513d602081101561182357600080fd5b505161186a576040805162461bcd60e51b8152602060048201526011602482015270105cdcd95d081d5b9cdd5c1c1bdc9d1959607a1b604482015290519081900360640190fd5b826001600160a01b031663d9caed128389898581811061188657fe5b905060200201356001600160a01b03168888868181106118a257fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561191157600080fd5b505af1158015611925573d6000803e3d6000fd5b5050600190920191506117809050565b50806001600160a01b031663de5f62686040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561197157600080fd5b505af1158015611985573d6000803e3d6000fd5b505050505050505050505050565b603754604080516315d5220f60e31b81526001600160a01b03848116600483015291516000938493169163aea91078916024808301926020929190829003018186803b1580156119e257600080fd5b505afa1580156119f6573d6000803e3d6000fd5b505050506040513d6020811015611a0c57600080fd5b505190506305f5e100811015610af857506305f5e100610b0981600a63ffffffff61291316565b60415481565b603f546001600160a01b0316331480611a555750611a55612076565b611a905760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b670de0b6b3a7640000811115611add576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015290519081900360640190fd5b60398190556040805182815290517f41ecb23a0e7865b25f38c268b7c3012220d822929e9edff07326e89d5bb822b59181900360200190a150565b603f546001600160a01b0316331480611b345750611b34612076565b611b6f5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a81b191690556040517f891ebab18da80ebeeea06b1b1cede098329c4c008906a98370c2ac7a80b571cb90600090a1565b603a5481565b6040602081905260009182529020546001600160a01b031681565b611bd0612076565b611c0f576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603e80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b611c6b612076565b611caa576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603a8190556040805182815290517f2ec5fb5a3d2703edc461252d92ccd2799c3c74f01d97212b20388207fa17ae459181900360200190a150565b6037546001600160a01b031681565b611cfc612076565b611d3b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603b8190556040805182815290517f39367850377ac04920a9a670f2180e7a94d83b15ad302e59875ec58fd10bd37d9181900360200190a150565b603f546001600160a01b0316331480611d925750611d92612076565b611dcd5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b604080516001600160a01b0380851682528316602082015281517fba58ce12801c949fa65f41c46ed108671c219baf945fa48d21026cea99ff252a929181900390910190a16001600160a01b03811660009081526035602052604090205460ff16611e77576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260336020526040902054819060ff16611edf576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b806001600160a01b031663aa388af6846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611f3557600080fd5b505afa158015611f49573d6000803e3d6000fd5b505050506040513d6020811015611f5f57600080fd5b5051611fb2576040805162461bcd60e51b815260206004820152601f60248201527f4173736574206e6f7420737570706f7274656420627920537472617465677900604482015290519081900360640190fd5b506001600160a01b03918216600090815260406020819052902080546001600160a01b03191691909216179055565b603f546001600160a01b0316331480611ffd5750611ffd612076565b6120385760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a01b1916600160a01b1790556040517f8cff26a5985614b3d30629cc4ab83824bf115aec971b718d8f2f99562032e97290600090a1565b6000612080612357565b6001600160a01b0316336001600160a01b031614905090565b603f546001600160a01b03163314806120b557506120b5612076565b6120f05760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b60005b60365481101561115e5760006036828154811061210c57fe5b60009182526020822001546040805163429c145b60e11b815290516001600160a01b039092169350839263853828b69260048084019382900301818387803b15801561215757600080fd5b505af115801561216b573d6000803e3d6000fd5b5050600190930192506120f3915050565b612184612076565b6121c3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6121cc81612a3f565b806001600160a01b03166121de612357565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b603754600160a81b900460ff1681565b61222e612076565b61226d576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b60388190556040805182815290517fd6c7508d6658ccee36b7b7d7fd72e5cbaeefb40c64eff24e9ae7470e846304ee9181900360200190a150565b6122b0612076565b6122ef576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6122f881612a63565b6123335760405162461bcd60e51b8152600401808060200182810382526024815260200180612f2c6024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606060008290506000816001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156123be57600080fd5b505afa1580156123d2573d6000803e3d6000fd5b505050506040513d60208110156123e857600080fd5b505190506001600160a01b038116156128b557816001600160a01b0316630242241d6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561243657600080fd5b505af115801561244a573d6000803e3d6000fd5b5050603e546001600160a01b03161591506128b59050576000826001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b15801561249c57600080fd5b505afa1580156124b0573d6000803e3d6000fd5b505050506040513d60208110156124c657600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561251457600080fd5b505afa158015612528573d6000803e3d6000fd5b505050506040513d602081101561253e57600080fd5b5051905080156128b257603e54612569906001600160a01b038481169116600063ffffffff612a9f16565b603e54612589906001600160a01b0384811691168363ffffffff612a9f16565b60408051600380825260808201909252606091602082018380388339019050509050846001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e457600080fd5b505afa1580156125f8573d6000803e3d6000fd5b505050506040513d602081101561260e57600080fd5b50518151829060009061261d57fe5b6001600160a01b03928316602091820292909201810191909152603e54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561267157600080fd5b505afa158015612685573d6000803e3d6000fd5b505050506040513d602081101561269b57600080fd5b50518151829060019081106126ac57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060346001815481106126da57fe5b9060005260206000200160009054906101000a90046001600160a01b03168160028151811061270557fe5b6001600160a01b039283166020918202929092010152603e54166338ed1739836000843061273b4261070863ffffffff612bb216565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b838110156127b457818101518382015260200161279c565b505050509050019650505050505050600060405180830381600087803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561281a57600080fd5b810190808051604051939291908464010000000082111561283a57600080fd5b90830190602082018581111561284f57600080fd5b825186602082028301116401000000008211171561286c57600080fd5b82525081516020918201928201910280838360005b83811015612899578181015183820152602001612881565b5050505090500160405250505095505050505050610988565b50505b5050919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261290e908490612c0c565b505050565b6000808260000b131561293e5761293783600084900b600a0a63ffffffff612dca16565b9250612966565b60008260000b121561296657612963836000848103900b600a0a63ffffffff612e2316565b92505b50815b92915050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b0381166129ef576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316612a01612357565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a361115e81612e65565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612a9757508115155b949350505050565b801580612b25575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015612af757600080fd5b505afa158015612b0b573d6000803e3d6000fd5b505050506040513d6020811015612b2157600080fd5b5051155b612b605760405162461bcd60e51b81526004018080602001828103825260368152602001806130136036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261290e908490612c0c565b600082820183811015610b09576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612c1e826001600160a01b0316612a63565b612c6f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612cad5780518252601f199092019160209182019101612c8e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612d0f576040519150601f19603f3d011682016040523d82523d6000602084013e612d14565b606091505b509150915081612d6b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612dc457808060200190516020811015612d8757600080fd5b5051612dc45760405162461bcd60e51b815260040180806020018281038252602a815260200180612fe9602a913960400191505060405180910390fd5b50505050565b600082612dd957506000612969565b82820282848281612de657fe5b0414610b095760405162461bcd60e51b8152600401808060200182810382526021815260200180612f986021913960400191505060405180910390fd5b6000610b0983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612e89565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008183612f155760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612eda578181015183820152602001612ec2565b50505050905090810190601f168015612f075780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612f2157fe5b049594505050505056fe6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637443616c6c6572206973206e6f74207468652053747261746567697374206f7220476f7665726e6f7243616c6c6572206973206e6f742074686520476f7665726e6f72000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f7420746865205661756c742c20476f7665726e6f722c206f7220537472617465676973745361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820e94b2b8fd98de32dfe8ffdf996c6bf9691663e7573f493e264a8b4d0c4a0f08864736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102745760003560e01c80635d36b19011610151578063b2c9336d116100c3578063c7af335211610087578063c7af33521461072b578063c991911214610733578063d38bfff41461073b578063e6cc543214610761578063eb03654b14610769578063fc0cfeee1461078657610274565b8063b2c9336d146106b3578063b888879e146106d0578063b890ebf6146106d8578063bc90106b146106f5578063c5f008411461072357610274565b80638e510b52116101155780638e510b52146106325780638ec489a21461063a57806394828ffd146106575780639fa1826e1461065f578063a403e4d514610667578063aea173d51461068d57610274565b80635d36b190146104e6578063663e64ce146104ee578063773540b31461050b5780637fe2d393146105315780638c5cbb891461060c57610274565b80632da845a8116101ea57806349c1d54d116101ae57806349c1d54d146104665780634cd55c2d1461046e57806352d38e5d1461049457806353ca9f241461049c578063570d8e1d146104b8578063597c8910146104c057610274565b80632da845a8146103e4578063372aa2241461040a5780633b8ae397146104305780633dbc911f146104565780634641257d1461045e57610274565b80631072cbea1161023c5780631072cbea1461035457806310d3fdac14610380578063128a8b05146103a6578063175188e8146103ae5780631edfe3da146103d4578063207134b0146103dc57610274565b806309f49bf51461027957806309f6442c146102835780630acbda751461029d5780630c340a24146102ba5780630e5c011e146102de575b600080fd5b6102816107ac565b005b61028b61082b565b60408051918252519081900360200190f35b610281600480360360208110156102b357600080fd5b5035610831565b6102c261090a565b604080516001600160a01b039092168252519081900360200190f35b610304600480360360208110156102f457600080fd5b50356001600160a01b0316610919565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610340578181015183820152602001610328565b505050509050019250505060405180910390f35b6102816004803603604081101561036a57600080fd5b506001600160a01b03813516906020013561098d565b61028b6004803603602081101561039657600080fd5b50356001600160a01b0316610a68565b6102c2610b10565b610281600480360360208110156103c457600080fd5b50356001600160a01b0316610b1f565b61028b610d83565b61028b610d89565b610281600480360360208110156103fa57600080fd5b50356001600160a01b0316610d8f565b6102816004803603602081101561042057600080fd5b50356001600160a01b0316610e2a565b6102816004803603602081101561044657600080fd5b50356001600160a01b0316610ec5565b610281611032565b6102816110c7565b6102c2611161565b6102816004803603602081101561048457600080fd5b50356001600160a01b0316611170565b61028b611344565b6104a461134a565b604080519115158252519081900360200190f35b6102c261135a565b610281600480360360208110156104d657600080fd5b50356001600160a01b0316611369565b610281611489565b6102816004803603602081101561050457600080fd5b50356114eb565b6102816004803603602081101561052157600080fd5b50356001600160a01b031661156d565b6102816004803603608081101561054757600080fd5b6001600160a01b03823581169260208101359091169181019060608101604082013564010000000081111561057b57600080fd5b82018360208201111561058d57600080fd5b803590602001918460208302840111640100000000831117156105af57600080fd5b9193909290916020810190356401000000008111156105cd57600080fd5b8201836020820111156105df57600080fd5b8035906020019184602083028401116401000000008311171561060157600080fd5b509092509050611608565b61028b6004803603602081101561062257600080fd5b50356001600160a01b0316611993565b61028b611a33565b6102816004803603602081101561065057600080fd5b5035611a39565b610281611b18565b61028b611ba7565b6102c26004803603602081101561067d57600080fd5b50356001600160a01b0316611bad565b610281600480360360208110156106a357600080fd5b50356001600160a01b0316611bc8565b610281600480360360208110156106c957600080fd5b5035611c63565b6102c2611ce5565b610281600480360360208110156106ee57600080fd5b5035611cf4565b6102816004803603604081101561070b57600080fd5b506001600160a01b0381358116916020013516611d76565b610281611fe1565b6104a4612076565b610281612099565b6102816004803603602081101561075157600080fd5b50356001600160a01b031661217c565b6104a4612216565b6102816004803603602081101561077f57600080fd5b5035612226565b6102816004803603602081101561079c57600080fd5b50356001600160a01b03166122a8565b6107b4612076565b6107f3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6037805460ff60a01b191690556040517fbc044409505c95b6b851433df96e1beae715c909d8e7c1d6d7ab783300d4e3b990600090a1565b60385481565b610839612076565b610878576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6113888111156108cf576040805162461bcd60e51b815260206004820152601760248201527f62617369732063616e6e6f742065786365656420353025000000000000000000604482015290519081900360640190fd5b60438190556040805182815290517f56287a45051933ea374811b3d5d165033047be5572cac676f7c28b8be4f746c79181900360200190a150565b6000610914612357565b905090565b6060333014806109335750603f546001600160a01b031633145b806109415750610941612076565b61097c5760405162461bcd60e51b8152600401808060200182810382526030815260200180612fb96030913960400191505060405180910390fd5b6109858261237c565b90505b919050565b610995612076565b6109d4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526033602052604090205460ff1615610a42576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c7920756e737570706f7274656420617373657473000000000000000000604482015290519081900360640190fd5b610a64610a4d61090a565b6001600160a01b038416908363ffffffff6128bc16565b5050565b603754604080516315d5220f60e31b81526001600160a01b03848116600483015291516000938493169163aea91078916024808301926020929190829003018186803b158015610ab757600080fd5b505afa158015610acb573d6000803e3d6000fd5b505050506040513d6020811015610ae157600080fd5b505190506305f5e100811115610af857506305f5e1005b610b0981600a63ffffffff61291316565b9392505050565b603e546001600160a01b031681565b610b27612076565b610b66576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff16610bcb576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b60365460005b603654811015610c1d57826001600160a01b031660368281548110610bf257fe5b6000918252602090912001546001600160a01b03161415610c1557809150610c1d565b600101610bd1565b50603654811015610d6157603680546000198101908110610c3a57fe5b600091825260209091200154603680546001600160a01b039092169183908110610c6057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506036805480610c9957fe5b6001900381819060005260206000200160006101000a8154906001600160a01b03021916905590556000829050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d0157600080fd5b505af1158015610d15573d6000803e3d6000fd5b50505050610d228361237c565b50604080516001600160a01b038516815290517f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea49181900360200190a1505b506001600160a01b03166000908152603560205260409020805460ff19169055565b60395481565b60435481565b610d97612076565b610dd6576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1e4af5ac389e8cde1bdaa6830881b6c987c62a45cfb3b33d27d805cde3b577509181900360200190a150565b610e32612076565b610e71576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603780546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb266add5f3044b17d27db796af992cecbe413921b4e8aaaee03c719e16b9806a9181900360200190a150565b610ecd612076565b610f0c576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff1615610f7a576040805162461bcd60e51b815260206004820152601960248201527f537472617465677920616c726561647920617070726f76656400000000000000604482015290519081900360640190fd5b6040805180820182526001808252600060208084018281526001600160a01b038716808452603583528684209551865460ff19169015151786559051948401949094556036805493840181559091527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890910180546001600160a01b03191683179055825191825291517f960dd94cbb79169f09a4e445d58b895df2d9bffa5b31055d0932d801724a20d1929181900390910190a150565b603f546001600160a01b031633148061104e575061104e612076565b6110895760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a81b1916600160a81b1790556040517f71f0e5b62f846a22e0b4d159e516e62fa9c2b8eb570be15f83e67d98a2ee51e090600090a1565b603f546001600160a01b03163314806110e357506110e3612076565b61111e5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b60005b60365481101561115e576111556036828154811061113b57fe5b6000918252602090912001546001600160a01b031661237c565b50600101611121565b50565b6042546001600160a01b031681565b611178612076565b6111b7576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526033602052604090205460ff1615611225576040805162461bcd60e51b815260206004820152601760248201527f417373657420616c726561647920737570706f72746564000000000000000000604482015290519081900360640190fd5b604080516020808201835260018083526001600160a01b038581166000818152603385528681209551865460ff1916901515179095556034805493840181559094527f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c190910180546001600160a01b0319168417905560375484516315d5220f60e31b81526004810194909452935193169263aea91078926024808201939291829003018186803b1580156112d957600080fd5b505afa1580156112ed573d6000803e3d6000fd5b505050506040513d602081101561130357600080fd5b5050604080516001600160a01b038316815290517f4f1ac48525e50059cc1cc6e0e1940ece0dd653a4db4841538d6aef036be2fb7b9181900360200190a150565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b603f546001600160a01b03163314806113855750611385612076565b6113c05760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6001600160a01b03811660009081526035602052604090205460ff1661142d576040805162461bcd60e51b815260206004820152601960248201527f5374726174656779206973206e6f7420737570706f7274656400000000000000604482015290519081900360640190fd5b6000819050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561146d57600080fd5b505af1158015611481573d6000803e3d6000fd5b505050505050565b61149161296f565b6001600160a01b0316336001600160a01b0316146114e05760405162461bcd60e51b81526004018080602001828103825260308152602001806130496030913960400191505060405180910390fd5b6114e933612994565b565b6114f3612076565b611532576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b60418190556040805182815290517f95201f9c21f26877223b1ff4073936a6484c35495649e60e55730497aeb60d939181900360200190a150565b611575612076565b6115b4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603f80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee9181900360200190a150565b603f546001600160a01b03163314806116245750611624612076565b61165f5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6001600160a01b03861660009081526035602052604090205460ff166116c4576040805162461bcd60e51b8152602060048201526015602482015274496e76616c69642066726f6d20537472617465677960581b604482015290519081900360640190fd5b6001600160a01b03851660009081526035602052604090205460ff16611727576040805162461bcd60e51b8152602060048201526013602482015272496e76616c696420746f20537472617465677960681b604482015290519081900360640190fd5b82811461177b576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b858560005b8581101561193557816001600160a01b031663aa388af68888848181106117a357fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156117f957600080fd5b505afa15801561180d573d6000803e3d6000fd5b505050506040513d602081101561182357600080fd5b505161186a576040805162461bcd60e51b8152602060048201526011602482015270105cdcd95d081d5b9cdd5c1c1bdc9d1959607a1b604482015290519081900360640190fd5b826001600160a01b031663d9caed128389898581811061188657fe5b905060200201356001600160a01b03168888868181106118a257fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561191157600080fd5b505af1158015611925573d6000803e3d6000fd5b5050600190920191506117809050565b50806001600160a01b031663de5f62686040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561197157600080fd5b505af1158015611985573d6000803e3d6000fd5b505050505050505050505050565b603754604080516315d5220f60e31b81526001600160a01b03848116600483015291516000938493169163aea91078916024808301926020929190829003018186803b1580156119e257600080fd5b505afa1580156119f6573d6000803e3d6000fd5b505050506040513d6020811015611a0c57600080fd5b505190506305f5e100811015610af857506305f5e100610b0981600a63ffffffff61291316565b60415481565b603f546001600160a01b0316331480611a555750611a55612076565b611a905760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b670de0b6b3a7640000811115611add576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015290519081900360640190fd5b60398190556040805182815290517f41ecb23a0e7865b25f38c268b7c3012220d822929e9edff07326e89d5bb822b59181900360200190a150565b603f546001600160a01b0316331480611b345750611b34612076565b611b6f5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a81b191690556040517f891ebab18da80ebeeea06b1b1cede098329c4c008906a98370c2ac7a80b571cb90600090a1565b603a5481565b6040602081905260009182529020546001600160a01b031681565b611bd0612076565b611c0f576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603e80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b611c6b612076565b611caa576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603a8190556040805182815290517f2ec5fb5a3d2703edc461252d92ccd2799c3c74f01d97212b20388207fa17ae459181900360200190a150565b6037546001600160a01b031681565b611cfc612076565b611d3b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603b8190556040805182815290517f39367850377ac04920a9a670f2180e7a94d83b15ad302e59875ec58fd10bd37d9181900360200190a150565b603f546001600160a01b0316331480611d925750611d92612076565b611dcd5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b604080516001600160a01b0380851682528316602082015281517fba58ce12801c949fa65f41c46ed108671c219baf945fa48d21026cea99ff252a929181900390910190a16001600160a01b03811660009081526035602052604090205460ff16611e77576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260336020526040902054819060ff16611edf576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b806001600160a01b031663aa388af6846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611f3557600080fd5b505afa158015611f49573d6000803e3d6000fd5b505050506040513d6020811015611f5f57600080fd5b5051611fb2576040805162461bcd60e51b815260206004820152601f60248201527f4173736574206e6f7420737570706f7274656420627920537472617465677900604482015290519081900360640190fd5b506001600160a01b03918216600090815260406020819052902080546001600160a01b03191691909216179055565b603f546001600160a01b0316331480611ffd5750611ffd612076565b6120385760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a01b1916600160a01b1790556040517f8cff26a5985614b3d30629cc4ab83824bf115aec971b718d8f2f99562032e97290600090a1565b6000612080612357565b6001600160a01b0316336001600160a01b031614905090565b603f546001600160a01b03163314806120b557506120b5612076565b6120f05760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b60005b60365481101561115e5760006036828154811061210c57fe5b60009182526020822001546040805163429c145b60e11b815290516001600160a01b039092169350839263853828b69260048084019382900301818387803b15801561215757600080fd5b505af115801561216b573d6000803e3d6000fd5b5050600190930192506120f3915050565b612184612076565b6121c3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6121cc81612a3f565b806001600160a01b03166121de612357565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b603754600160a81b900460ff1681565b61222e612076565b61226d576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b60388190556040805182815290517fd6c7508d6658ccee36b7b7d7fd72e5cbaeefb40c64eff24e9ae7470e846304ee9181900360200190a150565b6122b0612076565b6122ef576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6122f881612a63565b6123335760405162461bcd60e51b8152600401808060200182810382526024815260200180612f2c6024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606060008290506000816001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156123be57600080fd5b505afa1580156123d2573d6000803e3d6000fd5b505050506040513d60208110156123e857600080fd5b505190506001600160a01b038116156128b557816001600160a01b0316630242241d6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561243657600080fd5b505af115801561244a573d6000803e3d6000fd5b5050603e546001600160a01b03161591506128b59050576000826001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b15801561249c57600080fd5b505afa1580156124b0573d6000803e3d6000fd5b505050506040513d60208110156124c657600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561251457600080fd5b505afa158015612528573d6000803e3d6000fd5b505050506040513d602081101561253e57600080fd5b5051905080156128b257603e54612569906001600160a01b038481169116600063ffffffff612a9f16565b603e54612589906001600160a01b0384811691168363ffffffff612a9f16565b60408051600380825260808201909252606091602082018380388339019050509050846001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e457600080fd5b505afa1580156125f8573d6000803e3d6000fd5b505050506040513d602081101561260e57600080fd5b50518151829060009061261d57fe5b6001600160a01b03928316602091820292909201810191909152603e54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561267157600080fd5b505afa158015612685573d6000803e3d6000fd5b505050506040513d602081101561269b57600080fd5b50518151829060019081106126ac57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060346001815481106126da57fe5b9060005260206000200160009054906101000a90046001600160a01b03168160028151811061270557fe5b6001600160a01b039283166020918202929092010152603e54166338ed1739836000843061273b4261070863ffffffff612bb216565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b838110156127b457818101518382015260200161279c565b505050509050019650505050505050600060405180830381600087803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561281a57600080fd5b810190808051604051939291908464010000000082111561283a57600080fd5b90830190602082018581111561284f57600080fd5b825186602082028301116401000000008211171561286c57600080fd5b82525081516020918201928201910280838360005b83811015612899578181015183820152602001612881565b5050505090500160405250505095505050505050610988565b50505b5050919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261290e908490612c0c565b505050565b6000808260000b131561293e5761293783600084900b600a0a63ffffffff612dca16565b9250612966565b60008260000b121561296657612963836000848103900b600a0a63ffffffff612e2316565b92505b50815b92915050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b0381166129ef576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316612a01612357565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a361115e81612e65565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612a9757508115155b949350505050565b801580612b25575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015612af757600080fd5b505afa158015612b0b573d6000803e3d6000fd5b505050506040513d6020811015612b2157600080fd5b5051155b612b605760405162461bcd60e51b81526004018080602001828103825260368152602001806130136036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261290e908490612c0c565b600082820183811015610b09576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612c1e826001600160a01b0316612a63565b612c6f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612cad5780518252601f199092019160209182019101612c8e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612d0f576040519150601f19603f3d011682016040523d82523d6000602084013e612d14565b606091505b509150915081612d6b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612dc457808060200190516020811015612d8757600080fd5b5051612dc45760405162461bcd60e51b815260040180806020018281038252602a815260200180612fe9602a913960400191505060405180910390fd5b50505050565b600082612dd957506000612969565b82820282848281612de657fe5b0414610b095760405162461bcd60e51b8152600401808060200182810382526021815260200180612f986021913960400191505060405180910390fd5b6000610b0983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612e89565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008183612f155760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612eda578181015183820152602001612ec2565b50505050905090810190601f168015612f075780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612f2157fe5b049594505050505056fe6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637443616c6c6572206973206e6f74207468652053747261746567697374206f7220476f7665726e6f7243616c6c6572206973206e6f742074686520476f7665726e6f72000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f7420746865205661756c742c20476f7665726e6f722c206f7220537472617465676973745361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820e94b2b8fd98de32dfe8ffdf996c6bf9691663e7573f493e264a8b4d0c4a0f08864736f6c634300050b0032", "devdoc": { "methods": { "approveStrategy(address)": { @@ -1026,19 +1050,19 @@ "pauseRebase()": { "details": "Set the deposit paused flag to true to prevent rebasing." }, - "priceUSDMint(string)": { - "details": "Returns the total price in 18 digit USD for a given asset. Using Min since min is what we use for mint pricing", + "priceUSDMint(address)": { + "details": "Returns the total price in 18 digit USD for a given asset. Never goes above 1, since that is how we price mints", "params": { - "symbol": "String symbol of the asset" + "asset": "address of the asset" }, - "return": "uint256 USD price of 1 of the asset" + "return": "uint256 USD price of 1 of the asset, in 18 decimal fixed" }, - "priceUSDRedeem(string)": { - "details": "Returns the total price in 18 digit USD for a given asset. Using Max since max is what we use for redeem pricing", + "priceUSDRedeem(address)": { + "details": "Returns the total price in 18 digit USD for a given asset. Never goes below 1, since that is how we price redeems", "params": { - "symbol": "String symbol of the asset" + "asset": "Addresss of the asset" }, - "return": "uint256 USD price of 1 of the asset" + "return": "uint256 USD price of 1 of the asset, in 18 decimal fixed" }, "reallocate(address,address,address[],uint256[])": { "params": { @@ -1142,6 +1166,15 @@ }, "unpauseRebase()": { "details": "Set the deposit paused flag to true to allow rebasing." + }, + "withdrawAllFromStrategies()": { + "details": "Withdraws all assets from all the strategies and sends assets to the Vault." + }, + "withdrawAllFromStrategy(address)": { + "details": "Withdraws all assets from the strategy and sends assets to the Vault.", + "params": { + "_strategyAddr": "Strategy address." + } } } }, diff --git a/contracts/deployments/mainnet/VaultCore.json b/contracts/deployments/mainnet/VaultCore.json index 4a0fb3652c..1276cc0fd8 100644 --- a/contracts/deployments/mainnet/VaultCore.json +++ b/contracts/deployments/mainnet/VaultCore.json @@ -1,5 +1,5 @@ { - "address": "0x3e803eEA623eE4793f0f49790A813811da5249f4", + "address": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", "abi": [ { "constant": true, @@ -816,42 +816,42 @@ "type": "event" } ], - "transactionHash": "0x5e6fae5891d060a0f1d907415ec49f5951b536687f90e94b56928a338f27373d", + "transactionHash": "0x2bb4dcc3341a628b2de438b9b0e7294c470f8ca4d3b9ad2b5ec5786b6c652350", "receipt": { "to": null, "from": "0x71F78361537A6f7B6818e7A760c8bC0146D93f50", - "contractAddress": "0x3e803eEA623eE4793f0f49790A813811da5249f4", - "transactionIndex": 128, - "gasUsed": "3252626", - "logsBloom": "0x00000000000000000002000000000000000000000000001000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000200000000000000000020000000000000000000000000000000000000000000000100000000000000000000", - "blockHash": "0x20d7ff5f34c346008f409d50046f36f420a868e7a93375f7645dbd313afe9191", - "transactionHash": "0x5e6fae5891d060a0f1d907415ec49f5951b536687f90e94b56928a338f27373d", + "contractAddress": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", + "transactionIndex": 9, + "gasUsed": "3137806", + "logsBloom": "0x00000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000800000000000001", + "blockHash": "0x820be6d39bd4deb192f62c2710c48fa0c6eb039283fa85a81592d4a74e50bf12", + "transactionHash": "0x2bb4dcc3341a628b2de438b9b0e7294c470f8ca4d3b9ad2b5ec5786b6c652350", "logs": [ { - "transactionIndex": 128, - "blockNumber": 11785186, - "transactionHash": "0x5e6fae5891d060a0f1d907415ec49f5951b536687f90e94b56928a338f27373d", - "address": "0x3e803eEA623eE4793f0f49790A813811da5249f4", + "transactionIndex": 9, + "blockNumber": 12104648, + "transactionHash": "0x2bb4dcc3341a628b2de438b9b0e7294c470f8ca4d3b9ad2b5ec5786b6c652350", + "address": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", "topics": [ "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x00000000000000000000000071f78361537a6f7b6818e7a760c8bc0146d93f50" ], "data": "0x", - "logIndex": 107, - "blockHash": "0x20d7ff5f34c346008f409d50046f36f420a868e7a93375f7645dbd313afe9191" + "logIndex": 27, + "blockHash": "0x820be6d39bd4deb192f62c2710c48fa0c6eb039283fa85a81592d4a74e50bf12" } ], - "blockNumber": 11785186, - "cumulativeGasUsed": "8816835", + "blockNumber": 12104648, + "cumulativeGasUsed": "3979924", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "c3af786fe12b6b771320281cb59e3482", - "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"redeemFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOusdAmount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultBuffer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllAssets\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getStrategyCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebaseThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"checkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"calculateRedeemOutputs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minimumUnitAmount\",\"type\":\"uint256\"}],\"name\":\"redeemAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumUnitAmount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxSupplyDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"isSupportedAsset\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoAllocateThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAssetCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetDefaultStrategies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"allocate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"priceProvider\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"capitalPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_assets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOusdAmount\",\"type\":\"uint256\"}],\"name\":\"mintMultiple\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImpl\",\"type\":\"address\"}],\"name\":\"setAdminImpl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"AssetSupported\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"AssetDefaultStrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebasePaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebaseUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"VaultBufferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"RedeemFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"PriceProviderUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"AllocateThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"RebaseThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyDiffChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_yield\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"YieldDistribution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"TrusteeFeeBpsChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"TrusteeAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allocate()\":{\"details\":\"Allocate unallocated funds on Vault to strategies.*\"},\"checkBalance(address)\":{\"params\":{\"_asset\":\"Address of asset\"},\"return\":\"uint256 Balance of asset in decimals of asset\"},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"getAllAssets()\":{\"details\":\"Return all asset addresses in order\"},\"getAssetCount()\":{\"details\":\"Return the number of assets suppported by the Vault.\"},\"getStrategyCount()\":{\"details\":\"Return the number of strategies active on the Vault.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"mint(address,uint256,uint256)\":{\"details\":\"Deposit a supported asset and mint OUSD.\",\"params\":{\"_amount\":\"Amount of the asset being deposited\",\"_asset\":\"Address of the asset being deposited\",\"_minimumOusdAmount\":\"Minimum OUSD to mint\"}},\"mintMultiple(address[],uint256[],uint256)\":{\"details\":\"Mint for multiple assets in the same call.\",\"params\":{\"_amounts\":\"Amount of each asset at the same index in the _assets to deposit.\",\"_assets\":\"Addresses of assets being deposited\",\"_minimumOusdAmount\":\"Minimum OUSD to mint\"}},\"rebase()\":{\"details\":\"Calculate the total value of assets held by the Vault and all strategies and update the supply of OUSD.\"},\"redeem(uint256,uint256)\":{\"details\":\"Withdraw a supported asset and burn OUSD.\",\"params\":{\"_amount\":\"Amount of OUSD to burn\",\"_minimumUnitAmount\":\"Minimum stablecoin units to receive in return\"}},\"redeemAll(uint256)\":{\"params\":{\"_minimumUnitAmount\":\"Minimum stablecoin units to receive in return\"}},\"setAdminImpl(address)\":{\"details\":\"set the implementation for the admin, this needs to be in a base class else we cannot set it\",\"params\":{\"newImpl\":\"address of the implementation\"}},\"totalValue()\":{\"details\":\"Determine the total value of assets held by the vault and its strategies.\",\"return\":\"uint256 value Total value in USD (1e18)\"},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}}}},\"userdoc\":{\"methods\":{\"allocate()\":{\"notice\":\"Allocate unallocated funds on Vault to strategies.\"},\"calculateRedeemOutputs(uint256)\":{\"notice\":\"Calculate the outputs for a redeem function, i.e. the mix of coins that will be returned\"},\"checkBalance(address)\":{\"notice\":\"Get the balance of an asset held in Vault and all strategies.\"},\"redeemAll(uint256)\":{\"notice\":\"Withdraw a supported asset and burn all OUSD.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/vault/VaultCore.sol\":\"VaultCore\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"@openzeppelin/upgrades/contracts/Initializable.sol\":{\"content\":\"pragma solidity >=0.4.24 <0.7.0;\\n\\n\\n/**\\n * @title Initializable\\n *\\n * @dev Helper contract to support initializer functions. To use it, replace\\n * the constructor with a function that has the `initializer` modifier.\\n * WARNING: Unlike constructors, initializer functions must be manually\\n * invoked. This applies both to deploying an Initializable contract, as well\\n * as extending an Initializable contract via inheritance.\\n * WARNING: When used with inheritance, manual care must be taken to not invoke\\n * a parent initializer twice, or ensure that all initializers are idempotent,\\n * because this is not dealt with automatically as with constructors.\\n */\\ncontract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to use in the initializer function of a contract.\\n */\\n modifier initializer() {\\n require(initializing || isConstructor() || !initialized, \\\"Contract instance has already been initialized\\\");\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function isConstructor() private view returns (bool) {\\n // extcodesize checks the size of the code stored in an address, and\\n // address returns the current address. Since the code is still not\\n // deployed when running a constructor, any checks on its code size will\\n // yield zero, making it an effective way to detect if a contract is\\n // under construction or not.\\n address self = address(this);\\n uint256 cs;\\n assembly { cs := extcodesize(self) }\\n return cs == 0;\\n }\\n\\n // Reserved storage space to allow for layout changes in the future.\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x9bfec92e36234ecc99b5d37230acb6cd1f99560233753162204104a4897e8721\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x01eab42b6d54fa5389598e0663c24680ecc017e2da848e8ea1c40aeaa8225eef\"},\"contracts/interfaces/IMinMaxOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IMinMaxOracle {\\n //Assuming 8 decimals\\n function priceMin(string calldata symbol) external view returns (uint256);\\n\\n function priceMax(string calldata symbol) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x164c8759ca5a8e39bbe1de6b2504098c543b2f15663c9d452e083418f8313f48\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to Lending platform.\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardToken() external;\\n\\n /**\\n * @dev The address of the reward token for the Strategy.\\n */\\n function rewardTokenAddress() external pure returns (address);\\n\\n /**\\n * @dev The threshold (denominated in the reward token) over which the\\n * vault will auto harvest on allocate calls.\\n */\\n function rewardLiquidationThreshold() external pure returns (uint256);\\n}\\n\",\"keccak256\":\"0xa9ef9546d60635c630e3446f270bc93f34593f5c77db8c671146f6c1eb0b2774\"},\"contracts/interfaces/IVault.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IVault {\\n event AssetSupported(address _asset);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event DepositsPaused();\\n event DepositsUnpaused();\\n\\n // Governable.sol\\n function transferGovernance(address _newGovernor) external;\\n\\n function claimGovernance() external;\\n\\n function governor() external view returns (address);\\n\\n // VaultAdmin.sol\\n function setPriceProvider(address _priceProvider) external;\\n\\n function priceProvider() external view returns (address);\\n\\n function setRedeemFeeBps(uint256 _redeemFeeBps) external;\\n\\n function redeemFeeBps() external view returns (uint256);\\n\\n function setVaultBuffer(uint256 _vaultBuffer) external;\\n\\n function vaultBuffer() external view returns (uint256);\\n\\n function setAutoAllocateThreshold(uint256 _threshold) external;\\n\\n function autoAllocateThreshold() external view returns (uint256);\\n\\n function setRebaseThreshold(uint256 _threshold) external;\\n\\n function rebaseThreshold() external view returns (uint256);\\n\\n function setStrategistAddr(address _address) external;\\n\\n function strategistAddr() external view returns (address);\\n\\n function setUniswapAddr(address _address) external;\\n\\n function uniswapAddr() external view returns (address);\\n\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;\\n\\n function maxSupplyDiff() external view returns (uint256);\\n\\n function setTrusteeAddress(address _address) external;\\n\\n function trusteeAddress() external view returns (address);\\n\\n function setTrusteeFeeBps(uint256 _basis) external;\\n\\n function trusteeFeeBps() external view returns (uint256);\\n\\n function supportAsset(address _asset) external;\\n\\n function approveStrategy(address _addr) external;\\n\\n function removeStrategy(address _addr) external;\\n\\n function setAssetDefaultStrategy(address _asset, address _strategy)\\n external;\\n\\n function assetDefaultStrategies(address _asset)\\n external\\n view\\n returns (address);\\n\\n function pauseRebase() external;\\n\\n function unpauseRebase() external;\\n\\n function rebasePaused() external view returns (bool);\\n\\n function pauseCapital() external;\\n\\n function unpauseCapital() external;\\n\\n function capitalPaused() external view returns (bool);\\n\\n function transferToken(address _asset, uint256 _amount) external;\\n\\n function harvest() external;\\n\\n function harvest(address _strategyAddr) external;\\n\\n function priceUSDMint(string calldata symbol)\\n external\\n view\\n returns (uint256);\\n\\n function priceUSDRedeem(string calldata symbol)\\n external\\n view\\n returns (uint256);\\n\\n // VaultCore.sol\\n function mint(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function mintMultiple(\\n address[] calldata _assets,\\n uint256[] calldata _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount) external;\\n\\n function redeemAll(uint256 _minimumUnitAmount) external;\\n\\n function allocate() external;\\n\\n function reallocate(\\n address _strategyFromAddress,\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external;\\n\\n function rebase() external;\\n\\n function totalValue() external view returns (uint256 value);\\n\\n function checkBalance() external view returns (uint256);\\n\\n function checkBalance(address _asset) external view returns (uint256);\\n\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function getAssetCount() external view returns (uint256);\\n\\n function getAllAssets() external view returns (address[] memory);\\n\\n function getStrategyCount() external view returns (uint256);\\n\\n function isSupportedAsset(address _asset) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x84271ee5504677f7ad8b808df40d16704d5e2b83a9cdb897208d8c7b3e6cb8bb\"},\"contracts/token/OUSD.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {\\n InitializableERC20Detailed\\n} from \\\"../utils/InitializableERC20Detailed.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\n/**\\n * NOTE that this is an ERC20 token but the invariant that the sum of\\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\\n * rebasing design. Any integrations with OUSD should be aware.\\n */\\n\\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n\\n event TotalSupplyUpdated(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n\\n enum RebaseOptions { NotSet, OptOut, OptIn }\\n\\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\\n uint256 public _totalSupply;\\n mapping(address => mapping(address => uint256)) private _allowances;\\n address public vaultAddress = address(0);\\n mapping(address => uint256) private _creditBalances;\\n uint256 public rebasingCredits;\\n uint256 public rebasingCreditsPerToken;\\n // Frozen address/credits are non rebasing (value is held in contracts which\\n // do not receive yield unless they explicitly opt in)\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) public nonRebasingCreditsPerToken;\\n mapping(address => RebaseOptions) public rebaseState;\\n\\n function initialize(\\n string calldata _nameArg,\\n string calldata _symbolArg,\\n address _vaultAddress\\n ) external onlyGovernor initializer {\\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\\n rebasingCreditsPerToken = 1e18;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Savings Manager contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return The total supply of OUSD.\\n */\\n function totalSupply() public view returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the _amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n if (_creditBalances[_account] == 0) return 0;\\n return\\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n return (_creditBalances[_account], _creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the _amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(\\n _value <= balanceOf(msg.sender),\\n \\\"Transfer greater than balance\\\"\\n );\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The _amount of tokens to be transferred.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(_value <= balanceOf(_from), \\\"Transfer greater than balance\\\");\\n\\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\\n _value\\n );\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Update the count of non rebasing credits in response to a transfer\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value Amount of OUSD to transfer\\n */\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\\n\\n // Credits deducted and credited might be different due to the\\n // differing creditsPerToken used by each account\\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\\n\\n _creditBalances[_from] = _creditBalances[_from].sub(\\n creditsDeducted,\\n \\\"Transfer amount exceeds balance\\\"\\n );\\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\\n\\n if (isNonRebasingTo && !isNonRebasingFrom) {\\n // Transfer to non-rebasing account from rebasing account, credits\\n // are removed from the non rebasing tally\\n nonRebasingSupply = nonRebasingSupply.add(_value);\\n // Update rebasingCredits by subtracting the deducted amount\\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\\n // Transfer to rebasing account from non-rebasing account\\n // Decreasing non-rebasing credits by the amount that was sent\\n nonRebasingSupply = nonRebasingSupply.sub(_value);\\n // Update rebasingCredits by adding the credited amount\\n rebasingCredits = rebasingCredits.add(creditsCredited);\\n }\\n }\\n\\n /**\\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n public\\n view\\n returns (uint256)\\n {\\n return _allowances[_owner][_spender];\\n }\\n\\n /**\\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\\n * msg.sender. This method is included for ERC20 compatibility.\\n * increaseAllowance and decreaseAllowance should be used instead.\\n * Changing an allowance with this method brings the risk that someone may transfer both\\n * the old and the new allowance - if they are both greater than zero - if a transfer\\n * transaction is mined before the later approve() call is mined.\\n *\\n * @param _spender The address which will spend the funds.\\n * @param _value The _amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) public returns (bool) {\\n _allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\\n * This method should be used instead of approve() to avoid the double approval vulnerability\\n * described above.\\n * @param _spender The address which will spend the funds.\\n * @param _addedValue The _amount of tokens to increase the allowance by.\\n */\\n function increaseAllowance(address _spender, uint256 _addedValue)\\n public\\n returns (bool)\\n {\\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\\n .add(_addedValue);\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\\n * @param _spender The address which will spend the funds.\\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\\n */\\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\\n public\\n returns (bool)\\n {\\n uint256 oldValue = _allowances[msg.sender][_spender];\\n if (_subtractedValue >= oldValue) {\\n _allowances[msg.sender][_spender] = 0;\\n } else {\\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\\n }\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Mints new tokens, increasing totalSupply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n _mint(_account, _amount);\\n }\\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 * - `to` cannot be the zero address.\\n */\\n function _mint(address _account, uint256 _amount) internal nonReentrant {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\\n\\n // If the account is non rebasing and doesn't have a set creditsPerToken\\n // then set it i.e. this is a mint from a fresh contract\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.add(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.add(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.add(_amount);\\n\\n require(_totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @dev Burns tokens, decreasing totalSupply.\\n */\\n function burn(address account, uint256 amount) external onlyVault {\\n _burn(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 nonReentrant {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n uint256 currentCredits = _creditBalances[_account];\\n\\n // Remove the credits, burning rounding errors\\n if (\\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\\n ) {\\n // Handle dust from rounding\\n _creditBalances[_account] = 0;\\n } else if (currentCredits > creditAmount) {\\n _creditBalances[_account] = _creditBalances[_account].sub(\\n creditAmount\\n );\\n } else {\\n revert(\\\"Remove exceeds balance\\\");\\n }\\n\\n // Remove from the credit tallies and non-rebasing supply\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.sub(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.sub(_amount);\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n if (nonRebasingCreditsPerToken[_account] != 0) {\\n return nonRebasingCreditsPerToken[_account];\\n } else {\\n return rebasingCreditsPerToken;\\n }\\n }\\n\\n /**\\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\\n * Also, ensure contracts are non-rebasing if they have not opted in.\\n * @param _account Address of the account.\\n */\\n function _isNonRebasingAccount(address _account) internal returns (bool) {\\n bool isContract = Address.isContract(_account);\\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\\n _ensureRebasingMigration(_account);\\n }\\n return nonRebasingCreditsPerToken[_account] > 0;\\n }\\n\\n /**\\n * @dev Ensures internal account for rebasing and non-rebasing credits and\\n * supply is updated following deployment of frozen yield change.\\n */\\n function _ensureRebasingMigration(address _account) internal {\\n if (nonRebasingCreditsPerToken[_account] == 0) {\\n // Set fixed credits per token for this account\\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\\n // Update non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\\n // Update credit tallies\\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\\n }\\n }\\n\\n /**\\n * @dev Add a contract address to the non rebasing exception list. I.e. the\\n * address's balance will be part of rebases so the account will be exposed\\n * to upside and downside.\\n */\\n function rebaseOptIn() public nonReentrant {\\n require(_isNonRebasingAccount(msg.sender), \\\"Account has not opted out\\\");\\n\\n // Convert balance into the same amount at the current exchange rate\\n uint256 newCreditBalance = _creditBalances[msg.sender]\\n .mul(rebasingCreditsPerToken)\\n .div(_creditsPerToken(msg.sender));\\n\\n // Decreasing non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\\n\\n _creditBalances[msg.sender] = newCreditBalance;\\n\\n // Increase rebasing credits, totalSupply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\\n\\n rebaseState[msg.sender] = RebaseOptions.OptIn;\\n\\n // Delete any fixed credits per token\\n delete nonRebasingCreditsPerToken[msg.sender];\\n }\\n\\n /**\\n * @dev Remove a contract address to the non rebasing exception list.\\n */\\n function rebaseOptOut() public nonReentrant {\\n require(!_isNonRebasingAccount(msg.sender), \\\"Account has not opted in\\\");\\n\\n // Increase non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\\n // Set fixed credits per token\\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\\n\\n // Decrease rebasing credits, total supply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\\n\\n // Mark explicitly opted out of rebasing\\n rebaseState[msg.sender] = RebaseOptions.OptOut;\\n }\\n\\n /**\\n * @dev Modify the supply without minting new tokens. This uses a change in\\n * the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n * @return uint256 representing the new total supply.\\n */\\n function changeSupply(uint256 _newTotalSupply)\\n external\\n onlyVault\\n nonReentrant\\n {\\n require(_totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (_totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n return;\\n }\\n\\n _totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\\n _totalSupply.sub(nonRebasingSupply)\\n );\\n\\n require(rebasingCreditsPerToken > 0, \\\"Invalid change in supply\\\");\\n\\n _totalSupply = rebasingCredits\\n .divPrecisely(rebasingCreditsPerToken)\\n .add(nonRebasingSupply);\\n\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n }\\n}\\n\",\"keccak256\":\"0xea89a8b152b363982ba8db340b1e20c3194b2e75a06630cbbf43e3c50fff61a4\"},\"contracts/utils/Helpers.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0xd2ca92e0af883dc1aec5b22caced274e59829e0e30a9e955dcc48b8d921f5cdc\"},\"contracts/utils/InitializableERC20Detailed.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/**\\n * @dev Optional functions from the ERC20 standard.\\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\\n */\\ncontract InitializableERC20Detailed is IERC20 {\\n // Storage gap to skip storage from prior to OUSD reset\\n uint256[100] private _____gap;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\\n * these values are immutable: they can only be set once during\\n * construction.\\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\\n */\\n function _initialize(\\n string memory nameArg,\\n string memory symbolArg,\\n uint8 decimalsArg\\n ) internal {\\n _name = nameArg;\\n _symbol = symbolArg;\\n _decimals = decimalsArg;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view 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 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.\\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 returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x7919369d0f3bd74b4f0ee78a682afe43f91b186cdd0708e303068e4feeb29007\"},\"contracts/utils/StableMath.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n// Based on StableMath from Stability Labs Pty. Ltd.\\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\\n\\nlibrary StableMath {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Scaling unit for use in specific calculations,\\n * where 1 * 10**18, or 1e18 represents a unit '1'\\n */\\n uint256 private constant FULL_SCALE = 1e18;\\n\\n /***************************************\\n Helpers\\n ****************************************/\\n\\n /**\\n * @dev Adjust the scale of an integer\\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\\n */\\n function scaleBy(uint256 x, int8 adjustment)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (adjustment > 0) {\\n x = x.mul(10**uint256(adjustment));\\n } else if (adjustment < 0) {\\n x = x.div(10**uint256(adjustment * -1));\\n }\\n return x;\\n }\\n\\n /***************************************\\n Precise Arithmetic\\n ****************************************/\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\\n return mulTruncateScale(x, y, FULL_SCALE);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @param scale Scale unit\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncateScale(\\n uint256 x,\\n uint256 y,\\n uint256 scale\\n ) internal pure returns (uint256) {\\n // e.g. assume scale = fullScale\\n // z = 10e18 * 9e17 = 9e36\\n uint256 z = x.mul(y);\\n // return 9e38 / 1e18 = 9e18\\n return z.div(scale);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit, rounded up to the closest base unit.\\n */\\n function mulTruncateCeil(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e17 * 17268172638 = 138145381104e17\\n uint256 scaled = x.mul(y);\\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\\n return ceil.div(FULL_SCALE);\\n }\\n\\n /**\\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\\n * @param x Left hand input to division\\n * @param y Right hand input to division\\n * @return Result after multiplying the left operand by the scale, and\\n * executing the division on the right hand input.\\n */\\n function divPrecisely(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e18 * 1e18 = 8e36\\n uint256 z = x.mul(FULL_SCALE);\\n // e.g. 8e36 / 10e18 = 8e17\\n return z.div(y);\\n }\\n}\\n\",\"keccak256\":\"0xa77fccf850feb6d54ba3a6530f92554caef8a67a1ceb573d4f8a5d1bf64ff9d2\"},\"contracts/vault/VaultCore.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Vault Contract\\n * @notice The Vault contract stores assets. On a deposit, OUSD will be minted\\n and sent to the depositor. On a withdrawal, OUSD will be burned and\\n assets will be sent to the withdrawer. The Vault accepts deposits of\\n interest form yield bearing strategies which will modify the supply\\n of OUSD.\\n * @author Origin Protocol Inc\\n */\\n\\nimport \\\"./VaultStorage.sol\\\";\\nimport { IMinMaxOracle } from \\\"../interfaces/IMinMaxOracle.sol\\\";\\nimport { IVault } from \\\"../interfaces/IVault.sol\\\";\\n\\ncontract VaultCore is VaultStorage {\\n uint256 constant MAX_UINT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\\n\\n /**\\n * @dev Verifies that the rebasing is not paused.\\n */\\n modifier whenNotRebasePaused() {\\n require(!rebasePaused, \\\"Rebasing paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Verifies that the deposits are not paused.\\n */\\n modifier whenNotCapitalPaused() {\\n require(!capitalPaused, \\\"Capital paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Deposit a supported asset and mint OUSD.\\n * @param _asset Address of the asset being deposited\\n * @param _amount Amount of the asset being deposited\\n * @param _minimumOusdAmount Minimum OUSD to mint\\n */\\n function mint(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external whenNotCapitalPaused nonReentrant {\\n require(assets[_asset].isSupported, \\\"Asset is not supported\\\");\\n require(_amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n uint256 price = IMinMaxOracle(priceProvider).priceMin(\\n Helpers.getSymbol(_asset)\\n );\\n if (price > 1e8) {\\n price = 1e8;\\n }\\n uint256 assetDecimals = Helpers.getDecimals(_asset);\\n uint256 unitAdjustedDeposit = _amount.scaleBy(int8(18 - assetDecimals));\\n uint256 priceAdjustedDeposit = _amount.mulTruncateScale(\\n price.scaleBy(int8(10)), // 18-8 because oracles have 8 decimals precision\\n 10**assetDecimals\\n );\\n\\n if (_minimumOusdAmount > 0) {\\n require(\\n priceAdjustedDeposit >= _minimumOusdAmount,\\n \\\"Mint amount lower than minimum\\\"\\n );\\n }\\n\\n emit Mint(msg.sender, priceAdjustedDeposit);\\n\\n // Rebase must happen before any transfers occur.\\n if (unitAdjustedDeposit >= rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n\\n // Mint matching OUSD\\n oUSD.mint(msg.sender, priceAdjustedDeposit);\\n\\n // Transfer the deposited coins to the vault\\n IERC20 asset = IERC20(_asset);\\n asset.safeTransferFrom(msg.sender, address(this), _amount);\\n\\n if (unitAdjustedDeposit >= autoAllocateThreshold) {\\n _allocate();\\n }\\n }\\n\\n /**\\n * @dev Mint for multiple assets in the same call.\\n * @param _assets Addresses of assets being deposited\\n * @param _amounts Amount of each asset at the same index in the _assets\\n * to deposit.\\n * @param _minimumOusdAmount Minimum OUSD to mint\\n */\\n function mintMultiple(\\n address[] calldata _assets,\\n uint256[] calldata _amounts,\\n uint256 _minimumOusdAmount\\n ) external whenNotCapitalPaused nonReentrant {\\n require(_assets.length == _amounts.length, \\\"Parameter length mismatch\\\");\\n\\n uint256 unitAdjustedTotal = 0;\\n uint256 priceAdjustedTotal = 0;\\n uint256[] memory assetPrices = _getAssetPrices(false);\\n for (uint256 j = 0; j < _assets.length; j++) {\\n // In memoriam\\n require(assets[_assets[j]].isSupported, \\\"Asset is not supported\\\");\\n require(_amounts[j] > 0, \\\"Amount must be greater than 0\\\");\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n if (_assets[j] == allAssets[i]) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n uint256 price = assetPrices[i];\\n if (price > 1e18) {\\n price = 1e18;\\n }\\n unitAdjustedTotal = unitAdjustedTotal.add(\\n _amounts[j].scaleBy(int8(18 - assetDecimals))\\n );\\n priceAdjustedTotal = priceAdjustedTotal.add(\\n _amounts[j].mulTruncateScale(price, 10**assetDecimals)\\n );\\n }\\n }\\n }\\n\\n if (_minimumOusdAmount > 0) {\\n require(\\n priceAdjustedTotal >= _minimumOusdAmount,\\n \\\"Mint amount lower than minimum\\\"\\n );\\n }\\n\\n emit Mint(msg.sender, priceAdjustedTotal);\\n\\n // Rebase must happen before any transfers occur.\\n if (unitAdjustedTotal >= rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n\\n oUSD.mint(msg.sender, priceAdjustedTotal);\\n\\n for (uint256 i = 0; i < _assets.length; i++) {\\n IERC20 asset = IERC20(_assets[i]);\\n asset.safeTransferFrom(msg.sender, address(this), _amounts[i]);\\n }\\n\\n if (unitAdjustedTotal >= autoAllocateThreshold) {\\n _allocate();\\n }\\n }\\n\\n /**\\n * @dev Withdraw a supported asset and burn OUSD.\\n * @param _amount Amount of OUSD to burn\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount)\\n public\\n whenNotCapitalPaused\\n nonReentrant\\n {\\n if (_amount > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n _redeem(_amount, _minimumUnitAmount);\\n }\\n\\n /**\\n * @dev Withdraw a supported asset and burn OUSD.\\n * @param _amount Amount of OUSD to burn\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function _redeem(uint256 _amount, uint256 _minimumUnitAmount) internal {\\n require(_amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n uint256 _totalSupply = oUSD.totalSupply();\\n uint256 _backingValue = _totalValue();\\n\\n if (maxSupplyDiff > 0) {\\n // Allow a max difference of maxSupplyDiff% between\\n // backing assets value and OUSD total supply\\n uint256 diff = _totalSupply.divPrecisely(_backingValue);\\n\\n require(\\n (diff > 1e18 ? diff.sub(1e18) : uint256(1e18).sub(diff)) <=\\n maxSupplyDiff,\\n \\\"Backing supply liquidity error\\\"\\n );\\n }\\n\\n emit Redeem(msg.sender, _amount);\\n\\n // Calculate redemption outputs\\n uint256[] memory outputs = _calculateRedeemOutputs(_amount);\\n // Send outputs\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n if (outputs[i] == 0) continue;\\n\\n IERC20 asset = IERC20(allAssets[i]);\\n\\n if (asset.balanceOf(address(this)) >= outputs[i]) {\\n // Use Vault funds first if sufficient\\n asset.safeTransfer(msg.sender, outputs[i]);\\n } else {\\n address strategyAddr = assetDefaultStrategies[allAssets[i]];\\n if (strategyAddr != address(0)) {\\n // Nothing in Vault, but something in Strategy, send from there\\n IStrategy strategy = IStrategy(strategyAddr);\\n strategy.withdraw(msg.sender, allAssets[i], outputs[i]);\\n } else {\\n // Cant find funds anywhere\\n revert(\\\"Liquidity error\\\");\\n }\\n }\\n }\\n\\n if (_minimumUnitAmount > 0) {\\n uint256 unitTotal = 0;\\n for (uint256 i = 0; i < outputs.length; i++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n unitTotal = unitTotal.add(\\n outputs[i].scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n require(\\n unitTotal >= _minimumUnitAmount,\\n \\\"Redeem amount lower than minimum\\\"\\n );\\n }\\n\\n oUSD.burn(msg.sender, _amount);\\n\\n // Until we can prove that we won't affect the prices of our assets\\n // by withdrawing them, this should be here.\\n // It's possible that a strategy was off on its asset total, perhaps\\n // a reward token sold for more or for less than anticipated.\\n if (_amount > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n }\\n\\n /**\\n * @notice Withdraw a supported asset and burn all OUSD.\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function redeemAll(uint256 _minimumUnitAmount)\\n external\\n whenNotCapitalPaused\\n nonReentrant\\n {\\n // Unfortunately we have to do balanceOf twice, the rebase may change\\n // the account balance\\n if (oUSD.balanceOf(msg.sender) > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n _redeem(oUSD.balanceOf(msg.sender), _minimumUnitAmount);\\n }\\n\\n /**\\n * @notice Allocate unallocated funds on Vault to strategies.\\n * @dev Allocate unallocated funds on Vault to strategies.\\n **/\\n function allocate() public whenNotCapitalPaused nonReentrant {\\n _allocate();\\n }\\n\\n /**\\n * @notice Allocate unallocated funds on Vault to strategies.\\n * @dev Allocate unallocated funds on Vault to strategies.\\n **/\\n function _allocate() internal {\\n uint256 vaultValue = _totalValueInVault();\\n // Nothing in vault to allocate\\n if (vaultValue == 0) return;\\n uint256 strategiesValue = _totalValueInStrategies();\\n // We have a method that does the same as this, gas optimisation\\n uint256 calculatedTotalValue = vaultValue.add(strategiesValue);\\n\\n // We want to maintain a buffer on the Vault so calculate a percentage\\n // modifier to multiply each amount being allocated by to enforce the\\n // vault buffer\\n uint256 vaultBufferModifier;\\n if (strategiesValue == 0) {\\n // Nothing in Strategies, allocate 100% minus the vault buffer to\\n // strategies\\n vaultBufferModifier = uint256(1e18).sub(vaultBuffer);\\n } else {\\n vaultBufferModifier = vaultBuffer.mul(calculatedTotalValue).div(\\n vaultValue\\n );\\n if (1e18 > vaultBufferModifier) {\\n // E.g. 1e18 - (1e17 * 10e18)/5e18 = 8e17\\n // (5e18 * 8e17) / 1e18 = 4e18 allocated from Vault\\n vaultBufferModifier = uint256(1e18).sub(vaultBufferModifier);\\n } else {\\n // We need to let the buffer fill\\n return;\\n }\\n }\\n if (vaultBufferModifier == 0) return;\\n\\n // Iterate over all assets in the Vault and allocate the the appropriate\\n // strategy\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n IERC20 asset = IERC20(allAssets[i]);\\n uint256 assetBalance = asset.balanceOf(address(this));\\n // No balance, nothing to do here\\n if (assetBalance == 0) continue;\\n\\n // Multiply the balance by the vault buffer modifier and truncate\\n // to the scale of the asset decimals\\n uint256 allocateAmount = assetBalance.mulTruncate(\\n vaultBufferModifier\\n );\\n\\n address depositStrategyAddr = assetDefaultStrategies[address(\\n asset\\n )];\\n\\n if (depositStrategyAddr != address(0) && allocateAmount > 0) {\\n IStrategy strategy = IStrategy(depositStrategyAddr);\\n // Transfer asset to Strategy and call deposit method to\\n // mint or take required action\\n asset.safeTransfer(address(strategy), allocateAmount);\\n strategy.deposit(address(asset), allocateAmount);\\n }\\n }\\n\\n // Harvest for all reward tokens above reward liquidation threshold\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n address rewardTokenAddress = strategy.rewardTokenAddress();\\n if (rewardTokenAddress != address(0)) {\\n uint256 liquidationThreshold = strategy\\n .rewardLiquidationThreshold();\\n if (liquidationThreshold == 0) {\\n // No threshold set, always harvest from strategy\\n IVault(address(this)).harvest(allStrategies[i]);\\n } else {\\n // Check balance against liquidation threshold\\n // Note some strategies don't hold the reward token balance\\n // on their contract so the liquidation threshold should be\\n // set to 0\\n IERC20 rewardToken = IERC20(rewardTokenAddress);\\n uint256 rewardTokenAmount = rewardToken.balanceOf(\\n allStrategies[i]\\n );\\n if (rewardTokenAmount >= liquidationThreshold) {\\n IVault(address(this)).harvest(allStrategies[i]);\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Calculate the total value of assets held by the Vault and all\\n * strategies and update the supply of OUSD.\\n */\\n function rebase() public whenNotRebasePaused nonReentrant {\\n _rebase();\\n }\\n\\n /**\\n * @dev Calculate the total value of assets held by the Vault and all\\n * strategies and update the supply of OUSD, optionaly sending a\\n * portion of the yield to the trustee.\\n */\\n function _rebase() internal whenNotRebasePaused {\\n uint256 ousdSupply = oUSD.totalSupply();\\n if (ousdSupply == 0) {\\n return;\\n }\\n uint256 vaultValue = _totalValue();\\n\\n // Yield fee collection\\n address _trusteeAddress = trusteeAddress; // gas savings\\n if (_trusteeAddress != address(0) && (vaultValue > ousdSupply)) {\\n uint256 yield = vaultValue.sub(ousdSupply);\\n uint256 fee = yield.mul(trusteeFeeBps).div(10000);\\n require(yield > fee, \\\"Fee must not be greater than yield\\\");\\n if (fee > 0) {\\n oUSD.mint(_trusteeAddress, fee);\\n }\\n emit YieldDistribution(_trusteeAddress, yield, fee);\\n }\\n\\n // Only rachet OUSD supply upwards\\n ousdSupply = oUSD.totalSupply(); // Final check should use latest value\\n if (vaultValue > ousdSupply) {\\n oUSD.changeSupply(vaultValue);\\n }\\n }\\n\\n /**\\n * @dev Determine the total value of assets held by the vault and its\\n * strategies.\\n * @return uint256 value Total value in USD (1e18)\\n */\\n function totalValue() external view returns (uint256 value) {\\n value = _totalValue();\\n }\\n\\n /**\\n * @dev Internal Calculate the total value of the assets held by the\\n * vault and its strategies.\\n * @return uint256 value Total value in USD (1e18)\\n */\\n function _totalValue() internal view returns (uint256 value) {\\n return _totalValueInVault().add(_totalValueInStrategies());\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held in Vault.\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInVault() internal view returns (uint256 value) {\\n for (uint256 y = 0; y < allAssets.length; y++) {\\n IERC20 asset = IERC20(allAssets[y]);\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\\n uint256 balance = asset.balanceOf(address(this));\\n if (balance > 0) {\\n value = value.add(balance.scaleBy(int8(18 - assetDecimals)));\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held in Strategies.\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInStrategies() internal view returns (uint256 value) {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n value = value.add(_totalValueInStrategy(allStrategies[i]));\\n }\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held by strategy.\\n * @param _strategyAddr Address of the strategy\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInStrategy(address _strategyAddr)\\n internal\\n view\\n returns (uint256 value)\\n {\\n IStrategy strategy = IStrategy(_strategyAddr);\\n for (uint256 y = 0; y < allAssets.length; y++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\\n if (strategy.supportsAsset(allAssets[y])) {\\n uint256 balance = strategy.checkBalance(allAssets[y]);\\n if (balance > 0) {\\n value = value.add(\\n balance.scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Get the balance of an asset held in Vault and all strategies.\\n * @param _asset Address of asset\\n * @return uint256 Balance of asset in decimals of asset\\n */\\n function checkBalance(address _asset) external view returns (uint256) {\\n return _checkBalance(_asset);\\n }\\n\\n /**\\n * @notice Get the balance of an asset held in Vault and all strategies.\\n * @param _asset Address of asset\\n * @return uint256 Balance of asset in decimals of asset\\n */\\n function _checkBalance(address _asset)\\n internal\\n view\\n returns (uint256 balance)\\n {\\n IERC20 asset = IERC20(_asset);\\n balance = asset.balanceOf(address(this));\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n if (strategy.supportsAsset(_asset)) {\\n balance = balance.add(strategy.checkBalance(_asset));\\n }\\n }\\n }\\n\\n /**\\n * @notice Get the balance of all assets held in Vault and all strategies.\\n * @return uint256 Balance of all assets (1e18)\\n */\\n function _checkBalance() internal view returns (uint256 balance) {\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n balance = balance.add(\\n _checkBalance(allAssets[i]).scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n }\\n\\n /**\\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\\n * coins that will be returned\\n */\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory)\\n {\\n return _calculateRedeemOutputs(_amount);\\n }\\n\\n /**\\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\\n * coins that will be returned.\\n * @return Array of amounts respective to the supported assets\\n */\\n function _calculateRedeemOutputs(uint256 _amount)\\n internal\\n view\\n returns (uint256[] memory outputs)\\n {\\n // We always give out coins in proportion to how many we have,\\n // Now if all coins were the same value, this math would easy,\\n // just take the percentage of each coin, and multiply by the\\n // value to be given out. But if coins are worth more than $1,\\n // then we would end up handing out too many coins. We need to\\n // adjust by the total value of coins.\\n //\\n // To do this, we total up the value of our coins, by their\\n // percentages. Then divide what we would otherwise give out by\\n // this number.\\n //\\n // Let say we have 100 DAI at $1.06 and 200 USDT at $1.00.\\n // So for every 1 DAI we give out, we'll be handing out 2 USDT\\n // Our total output ratio is: 33% * 1.06 + 66% * 1.00 = 1.02\\n //\\n // So when calculating the output, we take the percentage of\\n // each coin, times the desired output value, divided by the\\n // totalOutputRatio.\\n //\\n // For example, withdrawing: 30 OUSD:\\n // DAI 33% * 30 / 1.02 = 9.80 DAI\\n // USDT = 66 % * 30 / 1.02 = 19.60 USDT\\n //\\n // Checking these numbers:\\n // 9.80 DAI * 1.06 = $10.40\\n // 19.60 USDT * 1.00 = $19.60\\n //\\n // And so the user gets $10.40 + $19.60 = $30 worth of value.\\n\\n uint256 assetCount = getAssetCount();\\n uint256[] memory assetPrices = _getAssetPrices(true);\\n uint256[] memory assetBalances = new uint256[](assetCount);\\n uint256[] memory assetDecimals = new uint256[](assetCount);\\n uint256 totalBalance = 0;\\n uint256 totalOutputRatio = 0;\\n outputs = new uint256[](assetCount);\\n\\n // Calculate redeem fee\\n if (redeemFeeBps > 0) {\\n uint256 redeemFee = _amount.mul(redeemFeeBps).div(10000);\\n _amount = _amount.sub(redeemFee);\\n }\\n\\n // Calculate assets balances and decimals once,\\n // for a large gas savings.\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 balance = _checkBalance(allAssets[i]);\\n uint256 decimals = Helpers.getDecimals(allAssets[i]);\\n assetBalances[i] = balance;\\n assetDecimals[i] = decimals;\\n totalBalance = totalBalance.add(\\n balance.scaleBy(int8(18 - decimals))\\n );\\n }\\n // Calculate totalOutputRatio\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 price = assetPrices[i];\\n // Never give out more than one\\n // stablecoin per dollar of OUSD\\n if (price < 1e18) {\\n price = 1e18;\\n }\\n uint256 ratio = assetBalances[i]\\n .scaleBy(int8(18 - assetDecimals[i]))\\n .mul(price)\\n .div(totalBalance);\\n totalOutputRatio = totalOutputRatio.add(ratio);\\n }\\n // Calculate final outputs\\n uint256 factor = _amount.divPrecisely(totalOutputRatio);\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n outputs[i] = assetBalances[i].mul(factor).div(totalBalance);\\n }\\n }\\n\\n /**\\n * @notice Get an array of the supported asset prices in USD.\\n * @return uint256[] Array of asset prices in USD (1e18)\\n */\\n function _getAssetPrices(bool useMax)\\n internal\\n view\\n returns (uint256[] memory assetPrices)\\n {\\n assetPrices = new uint256[](getAssetCount());\\n\\n IMinMaxOracle oracle = IMinMaxOracle(priceProvider);\\n // Price from Oracle is returned with 8 decimals\\n // _amount is in assetDecimals\\n\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n string memory symbol = Helpers.getSymbol(allAssets[i]);\\n // Get all the USD prices of the asset in 1e18\\n if (useMax) {\\n assetPrices[i] = oracle.priceMax(symbol).scaleBy(int8(18 - 8));\\n } else {\\n assetPrices[i] = oracle.priceMin(symbol).scaleBy(int8(18 - 8));\\n }\\n }\\n }\\n\\n /***************************************\\n Utils\\n ****************************************/\\n\\n /**\\n * @dev Return the number of assets suppported by the Vault.\\n */\\n function getAssetCount() public view returns (uint256) {\\n return allAssets.length;\\n }\\n\\n /**\\n * @dev Return all asset addresses in order\\n */\\n function getAllAssets() external view returns (address[] memory) {\\n return allAssets;\\n }\\n\\n /**\\n * @dev Return the number of strategies active on the Vault.\\n */\\n function getStrategyCount() external view returns (uint256) {\\n return allStrategies.length;\\n }\\n\\n function isSupportedAsset(address _asset) external view returns (bool) {\\n return assets[_asset].isSupported;\\n }\\n\\n /**\\n * @dev Falldown to the admin implementation\\n * @notice This is a catch all for all functions not declared in core\\n */\\n function() external payable {\\n bytes32 slot = adminImplPosition;\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize)\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas, sload(slot), 0, calldatasize, 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize)\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize)\\n }\\n default {\\n return(0, returndatasize)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9af2d88c824d11589927a4f7c1f60157ead5ca26352a4171139ece27a3b5b22d\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD VaultStorage Contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\n\\ncontract VaultStorage is Initializable, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n using SafeMath for int256;\\n using SafeERC20 for IERC20;\\n\\n event AssetSupported(address _asset);\\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\\n event PriceProviderUpdated(address _priceProvider);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event UniswapUpdated(address _address);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n\\n // Assets supported by the Vault, i.e. Stablecoins\\n struct Asset {\\n bool isSupported;\\n }\\n mapping(address => Asset) assets;\\n address[] allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n mapping(address => Strategy) strategies;\\n address[] allStrategies;\\n\\n // Address of the Oracle price provider contract\\n address public priceProvider;\\n // Pausing bools\\n bool public rebasePaused = false;\\n bool public capitalPaused = true;\\n // Redemption fee in basis points\\n uint256 public redeemFeeBps;\\n // Buffer of assets to keep in Vault to handle (most) withdrawals\\n uint256 public vaultBuffer;\\n // Mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n // Mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n OUSD oUSD;\\n\\n //keccak256(\\\"OUSD.vault.governor.admin.impl\\\");\\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\\n\\n // Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n // Address of Uniswap\\n address public uniswapAddr = address(0);\\n\\n // Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n // Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n mapping(address => address) public assetDefaultStrategies;\\n\\n uint256 public maxSupplyDiff;\\n\\n // Trustee address that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n // Amount of yield collected in basis points\\n uint256 public trusteeFeeBps;\\n\\n /**\\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\\n * @param newImpl address of the implementation\\n */\\n function setAdminImpl(address newImpl) external onlyGovernor {\\n require(\\n Address.isContract(newImpl),\\n \\\"new implementation is not a contract\\\"\\n );\\n bytes32 position = adminImplPosition;\\n assembly {\\n sstore(position, newImpl)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x02d224b70c086a3df5cf22792721aed5f278ddf4bc7b98b67ac9c38c767760a0\"}},\"version\":1}", - "bytecode": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b600080516020620039e783398151915255565b600080516020620039e78339815191525490565b6138f580620000f26000396000f3fe6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610b33565b3480156102ed57600080fd5b50610233610b39565b34801561030257600080fd5b5061030b610b3f565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610ba1565b34801561037c57600080fd5b5061025a610ba7565b34801561039157600080fd5b50610233610bb6565b3480156103a657600080fd5b506103af610bbc565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610bcc565b3480156103e457600080fd5b506102ca610bdb565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610c3d565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610c4e565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610c59565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610e29565b3480156104b057600080fd5b50610233610f10565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610f16565b3480156104f857600080fd5b50610233610f34565b34801561050d57600080fd5b50610233610f3a565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610f40565b34801561055557600080fd5b506102ca610f5b565b34801561056a57600080fd5b506102ca611016565b34801561057f57600080fd5b5061025a6110cb565b34801561059457600080fd5b506103af6110da565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b03166110fd565b3480156105dc57600080fd5b506102336111a9565b3480156105f157600080fd5b506103af6111b3565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b9193509150356111c3565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b03166116be565b60385481565b600061070c61177f565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b7833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b6037546000906001600160a01b03166319af6bf06108a4886117a4565b6040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156108f05781810151838201526020016108d8565b50505050905090810190601f16801561091d5780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b15801561093a57600080fd5b505afa15801561094e573d6000803e3d6000fd5b505050506040513d602081101561096457600080fd5b505190506305f5e10081111561097b57506305f5e1005b6000610986876118d5565b9050600061099e87601284900363ffffffff61198f16565b905060006109c86109b685600a63ffffffff61198f16565b8990600a86900a63ffffffff6119e916565b90508615610a255786811015610a25576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a7c5750603754600160a01b900460ff16155b15610a8957610a89611a17565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610adc57600080fd5b505af1158015610af0573d6000803e3d6000fd5b508b9250610b129150506001600160a01b03821633308c63ffffffff611d3e16565b603a548310610b2357610b23611d9e565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b9757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b79575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610be36122c1565b6001600160a01b0316336001600160a01b031614610c325760405162461bcd60e51b81526004018080602001828103825260308152602001806138916030913960400191505060405180910390fd5b610c3b336122e6565b565b6000610c4882612394565b92915050565b6060610c4882612555565b603754600160a81b900460ff1615610ca9576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415610d01576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b54603c54604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610d5357600080fd5b505afa158015610d67573d6000803e3d6000fd5b505050506040513d6020811015610d7d57600080fd5b5051118015610d965750603754600160a01b900460ff16155b15610da357610da3611a17565b603c54604080516370a0823160e01b81523360048201529051610e21926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d6020811015610e1957600080fd5b505184612816565b506001905550565b603754600160a81b900460ff1615610e79576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415610ed1576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b5484118015610ef05750603754600160a01b900460ff16155b15610efd57610efd611a17565b610f078484612816565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610fab576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415611003576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561100f611d9e565b5060019055565b603754600160a01b900460ff1615611067576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206137b7833981519152805460028114156110bf576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561100f611a17565b6037546001600160a01b031681565b60006110e461177f565b6001600160a01b0316336001600160a01b031614905090565b6111056110da565b611156576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61115f81612dc0565b806001600160a01b031661117161177f565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612de4565b603754600160a81b900460ff1681565b603754600160a81b900460ff1615611213576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b78339815191528054600281141561126b576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282558584146112c3576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b60008060606112d182612e05565b905060005b8981101561150a57603360008c8c848181106112ee57fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff1661135e576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061136c57fe5b90506020020135116113c5576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b60345481101561150157603481815481106113df57fe5b6000918252602090912001546001600160a01b03168c8c8481811061140057fe5b905060200201356001600160a01b03166001600160a01b031614156114f957600061144b6034838154811061143157fe5b6000918252602090912001546001600160a01b03166118d5565b9050600084838151811061145b57fe5b60200260200101519050670de0b6b3a76400008111156114805750670de0b6b3a76400005b6114b86114ab836012038e8e8881811061149657fe5b9050602002013561198f90919063ffffffff16565b889063ffffffff61300b16565b96506114f46114e78284600a0a8f8f898181106114d157fe5b905060200201356119e99092919063ffffffff16565b879063ffffffff61300b16565b955050505b6001016113c8565b506001016112d6565b5085156115665785821015611566576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b5483101580156115bd5750603754600160a01b900460ff16155b156115ca576115ca611a17565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b15801561161d57600080fd5b505af1158015611631573d6000803e3d6000fd5b506000925050505b8981101561169c5760008b8b8381811061164f57fe5b905060200201356001600160a01b0316905061169333308c8c8681811061167257fe5b90506020020135846001600160a01b0316611d3e909392919063ffffffff16565b50600101611639565b50603a5483106116ae576116ae611d9e565b5050506001825550505050505050565b6116c66110da565b611717576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6117208161306c565b61175b5760405162461bcd60e51b81526004018080602001828103825260248152602001806137d76024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606080826001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b1580156117e057600080fd5b505afa1580156117f4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561181d57600080fd5b810190808051604051939291908464010000000082111561183d57600080fd5b90830190602082018581111561185257600080fd5b825164010000000081118282018810171561186c57600080fd5b82525081516020918201929091019080838360005b83811015611899578181015183820152602001611881565b50505050905090810190601f1680156118c65780820380516001836020036101000a031916815260200191505b50604052509195945050505050565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561191157600080fd5b505afa158015611925573d6000803e3d6000fd5b505050506040513d602081101561193b57600080fd5b505160ff16905060048110801590611954575060128111155b610c485760405162461bcd60e51b81526004018080602001828103825260298152602001806137fb6029913960400191505060405180910390fd5b6000808260000b13156119ba576119b383600084900b600a0a63ffffffff6130a816565b92506119e2565b60008260000b12156119e2576119df836000848103900b600a0a63ffffffff61310116565b92505b5090919050565b6000806119fc858563ffffffff6130a816565b9050611a0e818463ffffffff61310116565b95945050505050565b603754600160a01b900460ff1615611a68576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015611aad57600080fd5b505afa158015611ac1573d6000803e3d6000fd5b505050506040513d6020811015611ad757600080fd5b5051905080611ae65750610c3b565b6000611af0612de4565b6042549091506001600160a01b03168015801590611b0d57508282115b15611c4f576000611b24838563ffffffff61314316565b90506000611b4f612710611b43604354856130a890919063ffffffff16565b9063ffffffff61310116565b9050808211611b8f5760405162461bcd60e51b81526004018080602001828103825260228152602001806138456022913960400191505060405180910390fd5b8015611c0357603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9d57600080fd5b505afa158015611cb1573d6000803e3d6000fd5b505050506040513d6020811015611cc757600080fd5b5051925082821115611d3957603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611d2057600080fd5b505af1158015611d34573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611d98908590613185565b50505050565b6000611da861333d565b905080611db55750610c3b565b6000611dbf61342d565b90506000611dd3838363ffffffff61300b16565b9050600082611dff57603954611df890670de0b6b3a76400009063ffffffff61314316565b9050611e4b565b611e1884611b43846039546130a890919063ffffffff16565b905080670de0b6b3a76400001115611e4257611df8670de0b6b3a76400008263ffffffff61314316565b50505050610c3b565b80611e595750505050610c3b565b60005b603454811015611fe857600060348281548110611e7557fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611ec857600080fd5b505afa158015611edc573d6000803e3d6000fd5b505050506040513d6020811015611ef257600080fd5b5051905080611f02575050611fe0565b6000611f14828663ffffffff61347f16565b6001600160a01b03808516600090815260406020819052902054919250168015801590611f415750600082115b15611fdb5780611f616001600160a01b038616828563ffffffff61349416565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611fc157600080fd5b505af1158015611fd5573d6000803e3d6000fd5b50505050505b505050505b600101611e5c565b5060005b6036548110156122ba5760006036828154811061200557fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b15801561205257600080fd5b505afa158015612066573d6000803e3d6000fd5b505050506040513d602081101561207c57600080fd5b505190506001600160a01b038116156122b0576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b1580156120ca57600080fd5b505afa1580156120de573d6000803e3d6000fd5b505050506040513d60208110156120f457600080fd5b505190508061218357306001600160a01b0316630e5c011e6036868154811061211957fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561216657600080fd5b505af115801561217a573d6000803e3d6000fd5b505050506122ae565b60008290506000816001600160a01b03166370a08231603688815481106121a657fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156121f457600080fd5b505afa158015612208573d6000803e3d6000fd5b505050506040513d602081101561221e57600080fd5b505190508281106122ab57306001600160a01b0316630e5c011e6036888154811061224557fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561229257600080fd5b505af11580156122a6573d6000803e3d6000fd5b505050505b50505b505b5050600101611fec565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116612341576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661235361177f565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3612391816134e6565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156123df57600080fd5b505afa1580156123f3573d6000803e3d6000fd5b505050506040513d602081101561240957600080fd5b5051915060005b60365481101561254e5760006036828154811061242957fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561247f57600080fd5b505afa158015612493573d6000803e3d6000fd5b505050506040513d60208110156124a957600080fd5b50511561254557612542816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561250957600080fd5b505afa15801561251d573d6000803e3d6000fd5b505050506040513d602081101561253357600080fd5b5051859063ffffffff61300b16565b93505b50600101612410565b5050919050565b60606000612561610f3a565b9050606061256f6001612e05565b905060608260405190808252806020026020018201604052801561259d578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156125cc578160200160208202803883390190505b5060408051868152602080880282010190915290915060009081908680156125fe578160200160208202803883390190505b506038549097501561263d576000612627612710611b436038548c6130a890919063ffffffff16565b9050612639898263ffffffff61314316565b9850505b60005b6034548110156126ed5760006126766034838154811061265c57fe5b6000918252602090912001546001600160a01b0316612394565b9050600061268a6034848154811061143157fe5b90508187848151811061269957fe5b602002602001018181525050808684815181106126b257fe5b60209081029190910101526126e16126d483601284900363ffffffff61198f16565b869063ffffffff61300b16565b94505050600101612640565b5060005b60345481101561279e57600086828151811061270957fe5b60200260200101519050670de0b6b3a764000081101561272e5750670de0b6b3a76400005b600061278085611b43846127748a888151811061274757fe5b60200260200101516012038c898151811061275e57fe5b602002602001015161198f90919063ffffffff16565b9063ffffffff6130a816565b9050612792848263ffffffff61300b16565b935050506001016126f1565b5060006127b1898363ffffffff61350a16565b905060005b603454811015612809576127ea84611b43848985815181106127d457fe5b60200260200101516130a890919063ffffffff16565b8982815181106127f657fe5b60209081029190910101526001016127b6565b5050505050505050919050565b6000821161286b576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b1580156128b057600080fd5b505afa1580156128c4573d6000803e3d6000fd5b505050506040513d60208110156128da57600080fd5b5051905060006128e8612de4565b604154909150156129a3576000612905838363ffffffff61350a16565b9050604154670de0b6b3a7640000821161293657612931670de0b6b3a76400008363ffffffff61314316565b61294e565b61294e82670de0b6b3a764000063ffffffff61314316565b11156129a1576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810186905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160606129e985612555565b905060005b603454811015612c7f57818181518110612a0457fe5b602002602001015160001415612a1957612c77565b600060348281548110612a2857fe5b60009182526020909120015483516001600160a01b039091169150839083908110612a4f57fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015612aad57600080fd5b505afa158015612ac1573d6000803e3d6000fd5b505050506040513d6020811015612ad757600080fd5b505110612b1457612b0f33848481518110612aee57fe5b6020026020010151836001600160a01b03166134949092919063ffffffff16565b612c75565b60006040600060348581548110612b2757fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612c34576000819050806001600160a01b031663d9caed123360348781548110612b7c57fe5b9060005260206000200160009054906101000a90046001600160a01b0316888881518110612ba657fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612c1657600080fd5b505af1158015612c2a573d6000803e3d6000fd5b5050505050612c73565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b6001016129ee565b508315612d2d576000805b8251811015612cd5576000612ca56034838154811061143157fe5b9050612cca612cbd8260120386858151811061275e57fe5b849063ffffffff61300b16565b925050600101612c8a565b5084811015612d2b576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612d8057600080fd5b505af1158015612d94573d6000803e3d6000fd5b50505050603b5485118015612db35750603754600160a01b900460ff16155b156122ba576122ba611a17565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612df161342d565b612df961333d565b9063ffffffff61300b16565b6060612e0f610f3a565b604051908082528060200260200182016040528015612e38578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561254e576060612e8160348381548110612e6757fe5b6000918252602090912001546001600160a01b03166117a4565b90508415612f8957612f6c600a846001600160a01b0316637bf0c215846040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612eea578181015183820152602001612ed2565b50505050905090810190601f168015612f175780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b158015612f3457600080fd5b505afa158015612f48573d6000803e3d6000fd5b505050506040513d6020811015612f5e57600080fd5b50519063ffffffff61198f16565b848381518110612f7857fe5b602002602001018181525050613002565b60405163019af6bf60e41b8152602060048201818152835160248401528351612fe993600a936001600160a01b038916936319af6bf093889391928392604401919085019080838360008315612eea578181015183820152602001612ed2565b848381518110612ff557fe5b6020026020010181815250505b50600101612e4b565b600082820183811015613065576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906130a057508115155b949350505050565b6000826130b757506000610c48565b828202828482816130c457fe5b04146130655760405162461bcd60e51b81526004018080602001828103825260218152602001806138246021913960400191505060405180910390fd5b600061306583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613537565b600061306583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506135d9565b613197826001600160a01b031661306c565b6131e8576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106132265780518252601f199092019160209182019101613207565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613288576040519150601f19603f3d011682016040523d82523d6000602084013e61328d565b606091505b5091509150816132e4576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611d985780806020019051602081101561330057600080fd5b5051611d985760405162461bcd60e51b815260040180806020018281038252602a815260200180613867602a913960400191505060405180910390fd5b6000805b6034548110156134295760006034828154811061335a57fe5b6000918252602082200154603480546001600160a01b039092169350613384918590811061143157fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156133d057600080fd5b505afa1580156133e4573d6000803e3d6000fd5b505050506040513d60208110156133fa57600080fd5b50519050801561341e5761341b6126d482601285900363ffffffff61198f16565b94505b505050600101613341565b5090565b6000805b603654811015613429576134756134686036838154811061344e57fe5b6000918252602090912001546001600160a01b0316613633565b839063ffffffff61300b16565b9150600101613431565b60006130658383670de0b6b3a76400006119e9565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611d39908490613185565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061352584670de0b6b3a764000063ffffffff6130a816565b90506130a0818463ffffffff61310116565b600081836135c35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613588578181015183820152602001613570565b50505050905090810190601f1680156135b55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816135cf57fe5b0495945050505050565b6000818484111561362b5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613588578181015183820152602001613570565b505050900390565b600081815b60345481101561254e5760006136546034838154811061143157fe5b9050826001600160a01b031663aa388af66034848154811061367257fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156136c057600080fd5b505afa1580156136d4573d6000803e3d6000fd5b505050506040513d60208110156136ea57600080fd5b5051156137ad576000836001600160a01b0316635f5152266034858154811061370f57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561375d57600080fd5b505afa158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5051905080156137ab576137a86126d482601285900363ffffffff61198f16565b94505b505b5060010161363856fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158209a486e46973c6f28f9c4d92884e27d910324137adbdaefaaa0cbbf675447effe64736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", - "deployedBytecode": "0x6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610b33565b3480156102ed57600080fd5b50610233610b39565b34801561030257600080fd5b5061030b610b3f565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610ba1565b34801561037c57600080fd5b5061025a610ba7565b34801561039157600080fd5b50610233610bb6565b3480156103a657600080fd5b506103af610bbc565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610bcc565b3480156103e457600080fd5b506102ca610bdb565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610c3d565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610c4e565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610c59565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610e29565b3480156104b057600080fd5b50610233610f10565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610f16565b3480156104f857600080fd5b50610233610f34565b34801561050d57600080fd5b50610233610f3a565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610f40565b34801561055557600080fd5b506102ca610f5b565b34801561056a57600080fd5b506102ca611016565b34801561057f57600080fd5b5061025a6110cb565b34801561059457600080fd5b506103af6110da565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b03166110fd565b3480156105dc57600080fd5b506102336111a9565b3480156105f157600080fd5b506103af6111b3565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b9193509150356111c3565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b03166116be565b60385481565b600061070c61177f565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b7833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b6037546000906001600160a01b03166319af6bf06108a4886117a4565b6040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156108f05781810151838201526020016108d8565b50505050905090810190601f16801561091d5780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b15801561093a57600080fd5b505afa15801561094e573d6000803e3d6000fd5b505050506040513d602081101561096457600080fd5b505190506305f5e10081111561097b57506305f5e1005b6000610986876118d5565b9050600061099e87601284900363ffffffff61198f16565b905060006109c86109b685600a63ffffffff61198f16565b8990600a86900a63ffffffff6119e916565b90508615610a255786811015610a25576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a7c5750603754600160a01b900460ff16155b15610a8957610a89611a17565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610adc57600080fd5b505af1158015610af0573d6000803e3d6000fd5b508b9250610b129150506001600160a01b03821633308c63ffffffff611d3e16565b603a548310610b2357610b23611d9e565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b9757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b79575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610be36122c1565b6001600160a01b0316336001600160a01b031614610c325760405162461bcd60e51b81526004018080602001828103825260308152602001806138916030913960400191505060405180910390fd5b610c3b336122e6565b565b6000610c4882612394565b92915050565b6060610c4882612555565b603754600160a81b900460ff1615610ca9576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415610d01576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b54603c54604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610d5357600080fd5b505afa158015610d67573d6000803e3d6000fd5b505050506040513d6020811015610d7d57600080fd5b5051118015610d965750603754600160a01b900460ff16155b15610da357610da3611a17565b603c54604080516370a0823160e01b81523360048201529051610e21926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d6020811015610e1957600080fd5b505184612816565b506001905550565b603754600160a81b900460ff1615610e79576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415610ed1576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b5484118015610ef05750603754600160a01b900460ff16155b15610efd57610efd611a17565b610f078484612816565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610fab576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415611003576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561100f611d9e565b5060019055565b603754600160a01b900460ff1615611067576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206137b7833981519152805460028114156110bf576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561100f611a17565b6037546001600160a01b031681565b60006110e461177f565b6001600160a01b0316336001600160a01b031614905090565b6111056110da565b611156576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61115f81612dc0565b806001600160a01b031661117161177f565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612de4565b603754600160a81b900460ff1681565b603754600160a81b900460ff1615611213576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b78339815191528054600281141561126b576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282558584146112c3576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b60008060606112d182612e05565b905060005b8981101561150a57603360008c8c848181106112ee57fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff1661135e576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061136c57fe5b90506020020135116113c5576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b60345481101561150157603481815481106113df57fe5b6000918252602090912001546001600160a01b03168c8c8481811061140057fe5b905060200201356001600160a01b03166001600160a01b031614156114f957600061144b6034838154811061143157fe5b6000918252602090912001546001600160a01b03166118d5565b9050600084838151811061145b57fe5b60200260200101519050670de0b6b3a76400008111156114805750670de0b6b3a76400005b6114b86114ab836012038e8e8881811061149657fe5b9050602002013561198f90919063ffffffff16565b889063ffffffff61300b16565b96506114f46114e78284600a0a8f8f898181106114d157fe5b905060200201356119e99092919063ffffffff16565b879063ffffffff61300b16565b955050505b6001016113c8565b506001016112d6565b5085156115665785821015611566576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b5483101580156115bd5750603754600160a01b900460ff16155b156115ca576115ca611a17565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b15801561161d57600080fd5b505af1158015611631573d6000803e3d6000fd5b506000925050505b8981101561169c5760008b8b8381811061164f57fe5b905060200201356001600160a01b0316905061169333308c8c8681811061167257fe5b90506020020135846001600160a01b0316611d3e909392919063ffffffff16565b50600101611639565b50603a5483106116ae576116ae611d9e565b5050506001825550505050505050565b6116c66110da565b611717576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6117208161306c565b61175b5760405162461bcd60e51b81526004018080602001828103825260248152602001806137d76024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606080826001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b1580156117e057600080fd5b505afa1580156117f4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561181d57600080fd5b810190808051604051939291908464010000000082111561183d57600080fd5b90830190602082018581111561185257600080fd5b825164010000000081118282018810171561186c57600080fd5b82525081516020918201929091019080838360005b83811015611899578181015183820152602001611881565b50505050905090810190601f1680156118c65780820380516001836020036101000a031916815260200191505b50604052509195945050505050565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561191157600080fd5b505afa158015611925573d6000803e3d6000fd5b505050506040513d602081101561193b57600080fd5b505160ff16905060048110801590611954575060128111155b610c485760405162461bcd60e51b81526004018080602001828103825260298152602001806137fb6029913960400191505060405180910390fd5b6000808260000b13156119ba576119b383600084900b600a0a63ffffffff6130a816565b92506119e2565b60008260000b12156119e2576119df836000848103900b600a0a63ffffffff61310116565b92505b5090919050565b6000806119fc858563ffffffff6130a816565b9050611a0e818463ffffffff61310116565b95945050505050565b603754600160a01b900460ff1615611a68576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015611aad57600080fd5b505afa158015611ac1573d6000803e3d6000fd5b505050506040513d6020811015611ad757600080fd5b5051905080611ae65750610c3b565b6000611af0612de4565b6042549091506001600160a01b03168015801590611b0d57508282115b15611c4f576000611b24838563ffffffff61314316565b90506000611b4f612710611b43604354856130a890919063ffffffff16565b9063ffffffff61310116565b9050808211611b8f5760405162461bcd60e51b81526004018080602001828103825260228152602001806138456022913960400191505060405180910390fd5b8015611c0357603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9d57600080fd5b505afa158015611cb1573d6000803e3d6000fd5b505050506040513d6020811015611cc757600080fd5b5051925082821115611d3957603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611d2057600080fd5b505af1158015611d34573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611d98908590613185565b50505050565b6000611da861333d565b905080611db55750610c3b565b6000611dbf61342d565b90506000611dd3838363ffffffff61300b16565b9050600082611dff57603954611df890670de0b6b3a76400009063ffffffff61314316565b9050611e4b565b611e1884611b43846039546130a890919063ffffffff16565b905080670de0b6b3a76400001115611e4257611df8670de0b6b3a76400008263ffffffff61314316565b50505050610c3b565b80611e595750505050610c3b565b60005b603454811015611fe857600060348281548110611e7557fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611ec857600080fd5b505afa158015611edc573d6000803e3d6000fd5b505050506040513d6020811015611ef257600080fd5b5051905080611f02575050611fe0565b6000611f14828663ffffffff61347f16565b6001600160a01b03808516600090815260406020819052902054919250168015801590611f415750600082115b15611fdb5780611f616001600160a01b038616828563ffffffff61349416565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611fc157600080fd5b505af1158015611fd5573d6000803e3d6000fd5b50505050505b505050505b600101611e5c565b5060005b6036548110156122ba5760006036828154811061200557fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b15801561205257600080fd5b505afa158015612066573d6000803e3d6000fd5b505050506040513d602081101561207c57600080fd5b505190506001600160a01b038116156122b0576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b1580156120ca57600080fd5b505afa1580156120de573d6000803e3d6000fd5b505050506040513d60208110156120f457600080fd5b505190508061218357306001600160a01b0316630e5c011e6036868154811061211957fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561216657600080fd5b505af115801561217a573d6000803e3d6000fd5b505050506122ae565b60008290506000816001600160a01b03166370a08231603688815481106121a657fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156121f457600080fd5b505afa158015612208573d6000803e3d6000fd5b505050506040513d602081101561221e57600080fd5b505190508281106122ab57306001600160a01b0316630e5c011e6036888154811061224557fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561229257600080fd5b505af11580156122a6573d6000803e3d6000fd5b505050505b50505b505b5050600101611fec565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116612341576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661235361177f565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3612391816134e6565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156123df57600080fd5b505afa1580156123f3573d6000803e3d6000fd5b505050506040513d602081101561240957600080fd5b5051915060005b60365481101561254e5760006036828154811061242957fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561247f57600080fd5b505afa158015612493573d6000803e3d6000fd5b505050506040513d60208110156124a957600080fd5b50511561254557612542816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561250957600080fd5b505afa15801561251d573d6000803e3d6000fd5b505050506040513d602081101561253357600080fd5b5051859063ffffffff61300b16565b93505b50600101612410565b5050919050565b60606000612561610f3a565b9050606061256f6001612e05565b905060608260405190808252806020026020018201604052801561259d578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156125cc578160200160208202803883390190505b5060408051868152602080880282010190915290915060009081908680156125fe578160200160208202803883390190505b506038549097501561263d576000612627612710611b436038548c6130a890919063ffffffff16565b9050612639898263ffffffff61314316565b9850505b60005b6034548110156126ed5760006126766034838154811061265c57fe5b6000918252602090912001546001600160a01b0316612394565b9050600061268a6034848154811061143157fe5b90508187848151811061269957fe5b602002602001018181525050808684815181106126b257fe5b60209081029190910101526126e16126d483601284900363ffffffff61198f16565b869063ffffffff61300b16565b94505050600101612640565b5060005b60345481101561279e57600086828151811061270957fe5b60200260200101519050670de0b6b3a764000081101561272e5750670de0b6b3a76400005b600061278085611b43846127748a888151811061274757fe5b60200260200101516012038c898151811061275e57fe5b602002602001015161198f90919063ffffffff16565b9063ffffffff6130a816565b9050612792848263ffffffff61300b16565b935050506001016126f1565b5060006127b1898363ffffffff61350a16565b905060005b603454811015612809576127ea84611b43848985815181106127d457fe5b60200260200101516130a890919063ffffffff16565b8982815181106127f657fe5b60209081029190910101526001016127b6565b5050505050505050919050565b6000821161286b576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b1580156128b057600080fd5b505afa1580156128c4573d6000803e3d6000fd5b505050506040513d60208110156128da57600080fd5b5051905060006128e8612de4565b604154909150156129a3576000612905838363ffffffff61350a16565b9050604154670de0b6b3a7640000821161293657612931670de0b6b3a76400008363ffffffff61314316565b61294e565b61294e82670de0b6b3a764000063ffffffff61314316565b11156129a1576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810186905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160606129e985612555565b905060005b603454811015612c7f57818181518110612a0457fe5b602002602001015160001415612a1957612c77565b600060348281548110612a2857fe5b60009182526020909120015483516001600160a01b039091169150839083908110612a4f57fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015612aad57600080fd5b505afa158015612ac1573d6000803e3d6000fd5b505050506040513d6020811015612ad757600080fd5b505110612b1457612b0f33848481518110612aee57fe5b6020026020010151836001600160a01b03166134949092919063ffffffff16565b612c75565b60006040600060348581548110612b2757fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612c34576000819050806001600160a01b031663d9caed123360348781548110612b7c57fe5b9060005260206000200160009054906101000a90046001600160a01b0316888881518110612ba657fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612c1657600080fd5b505af1158015612c2a573d6000803e3d6000fd5b5050505050612c73565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b6001016129ee565b508315612d2d576000805b8251811015612cd5576000612ca56034838154811061143157fe5b9050612cca612cbd8260120386858151811061275e57fe5b849063ffffffff61300b16565b925050600101612c8a565b5084811015612d2b576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612d8057600080fd5b505af1158015612d94573d6000803e3d6000fd5b50505050603b5485118015612db35750603754600160a01b900460ff16155b156122ba576122ba611a17565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612df161342d565b612df961333d565b9063ffffffff61300b16565b6060612e0f610f3a565b604051908082528060200260200182016040528015612e38578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561254e576060612e8160348381548110612e6757fe5b6000918252602090912001546001600160a01b03166117a4565b90508415612f8957612f6c600a846001600160a01b0316637bf0c215846040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612eea578181015183820152602001612ed2565b50505050905090810190601f168015612f175780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b158015612f3457600080fd5b505afa158015612f48573d6000803e3d6000fd5b505050506040513d6020811015612f5e57600080fd5b50519063ffffffff61198f16565b848381518110612f7857fe5b602002602001018181525050613002565b60405163019af6bf60e41b8152602060048201818152835160248401528351612fe993600a936001600160a01b038916936319af6bf093889391928392604401919085019080838360008315612eea578181015183820152602001612ed2565b848381518110612ff557fe5b6020026020010181815250505b50600101612e4b565b600082820183811015613065576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906130a057508115155b949350505050565b6000826130b757506000610c48565b828202828482816130c457fe5b04146130655760405162461bcd60e51b81526004018080602001828103825260218152602001806138246021913960400191505060405180910390fd5b600061306583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613537565b600061306583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506135d9565b613197826001600160a01b031661306c565b6131e8576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106132265780518252601f199092019160209182019101613207565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613288576040519150601f19603f3d011682016040523d82523d6000602084013e61328d565b606091505b5091509150816132e4576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611d985780806020019051602081101561330057600080fd5b5051611d985760405162461bcd60e51b815260040180806020018281038252602a815260200180613867602a913960400191505060405180910390fd5b6000805b6034548110156134295760006034828154811061335a57fe5b6000918252602082200154603480546001600160a01b039092169350613384918590811061143157fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156133d057600080fd5b505afa1580156133e4573d6000803e3d6000fd5b505050506040513d60208110156133fa57600080fd5b50519050801561341e5761341b6126d482601285900363ffffffff61198f16565b94505b505050600101613341565b5090565b6000805b603654811015613429576134756134686036838154811061344e57fe5b6000918252602090912001546001600160a01b0316613633565b839063ffffffff61300b16565b9150600101613431565b60006130658383670de0b6b3a76400006119e9565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611d39908490613185565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061352584670de0b6b3a764000063ffffffff6130a816565b90506130a0818463ffffffff61310116565b600081836135c35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613588578181015183820152602001613570565b50505050905090810190601f1680156135b55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816135cf57fe5b0495945050505050565b6000818484111561362b5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613588578181015183820152602001613570565b505050900390565b600081815b60345481101561254e5760006136546034838154811061143157fe5b9050826001600160a01b031663aa388af66034848154811061367257fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156136c057600080fd5b505afa1580156136d4573d6000803e3d6000fd5b505050506040513d60208110156136ea57600080fd5b5051156137ad576000836001600160a01b0316635f5152266034858154811061370f57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561375d57600080fd5b505afa158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5051905080156137ab576137a86126d482601285900363ffffffff61198f16565b94505b505b5060010161363856fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158209a486e46973c6f28f9c4d92884e27d910324137adbdaefaaa0cbbf675447effe64736f6c634300050b0032", + "solcInputHash": "cca309778b0bcb384ba7e2e97bde53a0", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"redeemFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOusdAmount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultBuffer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllAssets\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getStrategyCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebaseThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"checkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"calculateRedeemOutputs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minimumUnitAmount\",\"type\":\"uint256\"}],\"name\":\"redeemAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumUnitAmount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxSupplyDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"isSupportedAsset\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoAllocateThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAssetCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetDefaultStrategies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"allocate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"priceProvider\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"capitalPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_assets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOusdAmount\",\"type\":\"uint256\"}],\"name\":\"mintMultiple\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImpl\",\"type\":\"address\"}],\"name\":\"setAdminImpl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"AssetSupported\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"AssetDefaultStrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebasePaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebaseUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"VaultBufferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"RedeemFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"PriceProviderUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"AllocateThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"RebaseThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyDiffChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_yield\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"YieldDistribution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"TrusteeFeeBpsChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"TrusteeAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allocate()\":{\"details\":\"Allocate unallocated funds on Vault to strategies.*\"},\"checkBalance(address)\":{\"params\":{\"_asset\":\"Address of asset\"},\"return\":\"uint256 Balance of asset in decimals of asset\"},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"getAllAssets()\":{\"details\":\"Return all asset addresses in order\"},\"getAssetCount()\":{\"details\":\"Return the number of assets suppported by the Vault.\"},\"getStrategyCount()\":{\"details\":\"Return the number of strategies active on the Vault.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"mint(address,uint256,uint256)\":{\"details\":\"Deposit a supported asset and mint OUSD.\",\"params\":{\"_amount\":\"Amount of the asset being deposited\",\"_asset\":\"Address of the asset being deposited\",\"_minimumOusdAmount\":\"Minimum OUSD to mint\"}},\"mintMultiple(address[],uint256[],uint256)\":{\"details\":\"Mint for multiple assets in the same call.\",\"params\":{\"_amounts\":\"Amount of each asset at the same index in the _assets to deposit.\",\"_assets\":\"Addresses of assets being deposited\",\"_minimumOusdAmount\":\"Minimum OUSD to mint\"}},\"rebase()\":{\"details\":\"Calculate the total value of assets held by the Vault and all strategies and update the supply of OUSD.\"},\"redeem(uint256,uint256)\":{\"details\":\"Withdraw a supported asset and burn OUSD.\",\"params\":{\"_amount\":\"Amount of OUSD to burn\",\"_minimumUnitAmount\":\"Minimum stablecoin units to receive in return\"}},\"redeemAll(uint256)\":{\"params\":{\"_minimumUnitAmount\":\"Minimum stablecoin units to receive in return\"}},\"setAdminImpl(address)\":{\"details\":\"set the implementation for the admin, this needs to be in a base class else we cannot set it\",\"params\":{\"newImpl\":\"address of the implementation\"}},\"totalValue()\":{\"details\":\"Determine the total value of assets held by the vault and its strategies.\",\"return\":\"uint256 value Total value in USD (1e18)\"},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}}}},\"userdoc\":{\"methods\":{\"allocate()\":{\"notice\":\"Allocate unallocated funds on Vault to strategies.\"},\"calculateRedeemOutputs(uint256)\":{\"notice\":\"Calculate the outputs for a redeem function, i.e. the mix of coins that will be returned\"},\"checkBalance(address)\":{\"notice\":\"Get the balance of an asset held in Vault and all strategies.\"},\"redeemAll(uint256)\":{\"notice\":\"Withdraw a supported asset and burn all OUSD.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/vault/VaultCore.sol\":\"VaultCore\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"@openzeppelin/upgrades/contracts/Initializable.sol\":{\"content\":\"pragma solidity >=0.4.24 <0.7.0;\\n\\n\\n/**\\n * @title Initializable\\n *\\n * @dev Helper contract to support initializer functions. To use it, replace\\n * the constructor with a function that has the `initializer` modifier.\\n * WARNING: Unlike constructors, initializer functions must be manually\\n * invoked. This applies both to deploying an Initializable contract, as well\\n * as extending an Initializable contract via inheritance.\\n * WARNING: When used with inheritance, manual care must be taken to not invoke\\n * a parent initializer twice, or ensure that all initializers are idempotent,\\n * because this is not dealt with automatically as with constructors.\\n */\\ncontract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to use in the initializer function of a contract.\\n */\\n modifier initializer() {\\n require(initializing || isConstructor() || !initialized, \\\"Contract instance has already been initialized\\\");\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function isConstructor() private view returns (bool) {\\n // extcodesize checks the size of the code stored in an address, and\\n // address returns the current address. Since the code is still not\\n // deployed when running a constructor, any checks on its code size will\\n // yield zero, making it an effective way to detect if a contract is\\n // under construction or not.\\n address self = address(this);\\n uint256 cs;\\n assembly { cs := extcodesize(self) }\\n return cs == 0;\\n }\\n\\n // Reserved storage space to allow for layout changes in the future.\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x9bfec92e36234ecc99b5d37230acb6cd1f99560233753162204104a4897e8721\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x01eab42b6d54fa5389598e0663c24680ecc017e2da848e8ea1c40aeaa8225eef\"},\"contracts/interfaces/IBuyback.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBuyback {\\n function swap() external;\\n}\\n\",\"keccak256\":\"0xb85059a081297a310ede87d1eb30356d3c938e97488a99d1de0c65ebf26dc92d\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IOracle {\\n /**\\n * @dev returns the asset price in USD, 8 decimal digits.\\n */\\n function price(address asset) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x7ddbe1f9ed76feb2fbd52ecfe449e17ef67f7edd5616c6a1eda92a84baa1190f\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to platform\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Deposit the entire balance of all supported assets in the Strategy\\n * to the platform\\n */\\n function depositAll() external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardToken() external;\\n\\n /**\\n * @dev The address of the reward token for the Strategy.\\n */\\n function rewardTokenAddress() external pure returns (address);\\n\\n /**\\n * @dev The threshold (denominated in the reward token) over which the\\n * vault will auto harvest on allocate calls.\\n */\\n function rewardLiquidationThreshold() external pure returns (uint256);\\n}\\n\",\"keccak256\":\"0xe03dc1c97ad3677296da9a7e1e5f708abd227d1147f6f220c5cc8f23c1cd87e0\"},\"contracts/interfaces/IVault.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IVault {\\n event AssetSupported(address _asset);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event DepositsPaused();\\n event DepositsUnpaused();\\n\\n // Governable.sol\\n function transferGovernance(address _newGovernor) external;\\n\\n function claimGovernance() external;\\n\\n function governor() external view returns (address);\\n\\n // VaultAdmin.sol\\n function setPriceProvider(address _priceProvider) external;\\n\\n function priceProvider() external view returns (address);\\n\\n function setRedeemFeeBps(uint256 _redeemFeeBps) external;\\n\\n function redeemFeeBps() external view returns (uint256);\\n\\n function setVaultBuffer(uint256 _vaultBuffer) external;\\n\\n function vaultBuffer() external view returns (uint256);\\n\\n function setAutoAllocateThreshold(uint256 _threshold) external;\\n\\n function autoAllocateThreshold() external view returns (uint256);\\n\\n function setRebaseThreshold(uint256 _threshold) external;\\n\\n function rebaseThreshold() external view returns (uint256);\\n\\n function setStrategistAddr(address _address) external;\\n\\n function strategistAddr() external view returns (address);\\n\\n function setUniswapAddr(address _address) external;\\n\\n function uniswapAddr() external view returns (address);\\n\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;\\n\\n function maxSupplyDiff() external view returns (uint256);\\n\\n function setTrusteeAddress(address _address) external;\\n\\n function trusteeAddress() external view returns (address);\\n\\n function setTrusteeFeeBps(uint256 _basis) external;\\n\\n function trusteeFeeBps() external view returns (uint256);\\n\\n function supportAsset(address _asset) external;\\n\\n function approveStrategy(address _addr) external;\\n\\n function removeStrategy(address _addr) external;\\n\\n function setAssetDefaultStrategy(address _asset, address _strategy)\\n external;\\n\\n function assetDefaultStrategies(address _asset)\\n external\\n view\\n returns (address);\\n\\n function pauseRebase() external;\\n\\n function unpauseRebase() external;\\n\\n function rebasePaused() external view returns (bool);\\n\\n function pauseCapital() external;\\n\\n function unpauseCapital() external;\\n\\n function capitalPaused() external view returns (bool);\\n\\n function transferToken(address _asset, uint256 _amount) external;\\n\\n function harvest() external;\\n\\n function harvest(address _strategyAddr) external;\\n\\n function priceUSDMint(address asset) external view returns (uint256);\\n\\n function priceUSDRedeem(address asset) external view returns (uint256);\\n\\n function withdrawAllFromStrategy(address _strategyAddr) external;\\n\\n function withdrawAllFromStrategies() external;\\n\\n // VaultCore.sol\\n function mint(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function mintMultiple(\\n address[] calldata _assets,\\n uint256[] calldata _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount) external;\\n\\n function redeemAll(uint256 _minimumUnitAmount) external;\\n\\n function allocate() external;\\n\\n function reallocate(\\n address _strategyFromAddress,\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external;\\n\\n function rebase() external;\\n\\n function totalValue() external view returns (uint256 value);\\n\\n function checkBalance() external view returns (uint256);\\n\\n function checkBalance(address _asset) external view returns (uint256);\\n\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function getAssetCount() external view returns (uint256);\\n\\n function getAllAssets() external view returns (address[] memory);\\n\\n function getStrategyCount() external view returns (uint256);\\n\\n function isSupportedAsset(address _asset) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x3bf6745000b68ce59f9083d9f005cbe84853c4688acbdc7d37ebbba3dae8bdbc\"},\"contracts/token/OUSD.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {\\n InitializableERC20Detailed\\n} from \\\"../utils/InitializableERC20Detailed.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\n/**\\n * NOTE that this is an ERC20 token but the invariant that the sum of\\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\\n * rebasing design. Any integrations with OUSD should be aware.\\n */\\n\\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n\\n event TotalSupplyUpdated(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n\\n enum RebaseOptions { NotSet, OptOut, OptIn }\\n\\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\\n uint256 public _totalSupply;\\n mapping(address => mapping(address => uint256)) private _allowances;\\n address public vaultAddress = address(0);\\n mapping(address => uint256) private _creditBalances;\\n uint256 public rebasingCredits;\\n uint256 public rebasingCreditsPerToken;\\n // Frozen address/credits are non rebasing (value is held in contracts which\\n // do not receive yield unless they explicitly opt in)\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) public nonRebasingCreditsPerToken;\\n mapping(address => RebaseOptions) public rebaseState;\\n\\n function initialize(\\n string calldata _nameArg,\\n string calldata _symbolArg,\\n address _vaultAddress\\n ) external onlyGovernor initializer {\\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\\n rebasingCreditsPerToken = 1e18;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Savings Manager contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return The total supply of OUSD.\\n */\\n function totalSupply() public view returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the _amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n if (_creditBalances[_account] == 0) return 0;\\n return\\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n return (_creditBalances[_account], _creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the _amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(\\n _value <= balanceOf(msg.sender),\\n \\\"Transfer greater than balance\\\"\\n );\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The _amount of tokens to be transferred.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(_value <= balanceOf(_from), \\\"Transfer greater than balance\\\");\\n\\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\\n _value\\n );\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Update the count of non rebasing credits in response to a transfer\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value Amount of OUSD to transfer\\n */\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\\n\\n // Credits deducted and credited might be different due to the\\n // differing creditsPerToken used by each account\\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\\n\\n _creditBalances[_from] = _creditBalances[_from].sub(\\n creditsDeducted,\\n \\\"Transfer amount exceeds balance\\\"\\n );\\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\\n\\n if (isNonRebasingTo && !isNonRebasingFrom) {\\n // Transfer to non-rebasing account from rebasing account, credits\\n // are removed from the non rebasing tally\\n nonRebasingSupply = nonRebasingSupply.add(_value);\\n // Update rebasingCredits by subtracting the deducted amount\\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\\n // Transfer to rebasing account from non-rebasing account\\n // Decreasing non-rebasing credits by the amount that was sent\\n nonRebasingSupply = nonRebasingSupply.sub(_value);\\n // Update rebasingCredits by adding the credited amount\\n rebasingCredits = rebasingCredits.add(creditsCredited);\\n }\\n }\\n\\n /**\\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n public\\n view\\n returns (uint256)\\n {\\n return _allowances[_owner][_spender];\\n }\\n\\n /**\\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\\n * msg.sender. This method is included for ERC20 compatibility.\\n * increaseAllowance and decreaseAllowance should be used instead.\\n * Changing an allowance with this method brings the risk that someone may transfer both\\n * the old and the new allowance - if they are both greater than zero - if a transfer\\n * transaction is mined before the later approve() call is mined.\\n *\\n * @param _spender The address which will spend the funds.\\n * @param _value The _amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) public returns (bool) {\\n _allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\\n * This method should be used instead of approve() to avoid the double approval vulnerability\\n * described above.\\n * @param _spender The address which will spend the funds.\\n * @param _addedValue The _amount of tokens to increase the allowance by.\\n */\\n function increaseAllowance(address _spender, uint256 _addedValue)\\n public\\n returns (bool)\\n {\\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\\n .add(_addedValue);\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\\n * @param _spender The address which will spend the funds.\\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\\n */\\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\\n public\\n returns (bool)\\n {\\n uint256 oldValue = _allowances[msg.sender][_spender];\\n if (_subtractedValue >= oldValue) {\\n _allowances[msg.sender][_spender] = 0;\\n } else {\\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\\n }\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Mints new tokens, increasing totalSupply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n _mint(_account, _amount);\\n }\\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 * - `to` cannot be the zero address.\\n */\\n function _mint(address _account, uint256 _amount) internal nonReentrant {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\\n\\n // If the account is non rebasing and doesn't have a set creditsPerToken\\n // then set it i.e. this is a mint from a fresh contract\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.add(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.add(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.add(_amount);\\n\\n require(_totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @dev Burns tokens, decreasing totalSupply.\\n */\\n function burn(address account, uint256 amount) external onlyVault {\\n _burn(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 nonReentrant {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n uint256 currentCredits = _creditBalances[_account];\\n\\n // Remove the credits, burning rounding errors\\n if (\\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\\n ) {\\n // Handle dust from rounding\\n _creditBalances[_account] = 0;\\n } else if (currentCredits > creditAmount) {\\n _creditBalances[_account] = _creditBalances[_account].sub(\\n creditAmount\\n );\\n } else {\\n revert(\\\"Remove exceeds balance\\\");\\n }\\n\\n // Remove from the credit tallies and non-rebasing supply\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.sub(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.sub(_amount);\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n if (nonRebasingCreditsPerToken[_account] != 0) {\\n return nonRebasingCreditsPerToken[_account];\\n } else {\\n return rebasingCreditsPerToken;\\n }\\n }\\n\\n /**\\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\\n * Also, ensure contracts are non-rebasing if they have not opted in.\\n * @param _account Address of the account.\\n */\\n function _isNonRebasingAccount(address _account) internal returns (bool) {\\n bool isContract = Address.isContract(_account);\\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\\n _ensureRebasingMigration(_account);\\n }\\n return nonRebasingCreditsPerToken[_account] > 0;\\n }\\n\\n /**\\n * @dev Ensures internal account for rebasing and non-rebasing credits and\\n * supply is updated following deployment of frozen yield change.\\n */\\n function _ensureRebasingMigration(address _account) internal {\\n if (nonRebasingCreditsPerToken[_account] == 0) {\\n // Set fixed credits per token for this account\\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\\n // Update non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\\n // Update credit tallies\\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\\n }\\n }\\n\\n /**\\n * @dev Add a contract address to the non rebasing exception list. I.e. the\\n * address's balance will be part of rebases so the account will be exposed\\n * to upside and downside.\\n */\\n function rebaseOptIn() public nonReentrant {\\n require(_isNonRebasingAccount(msg.sender), \\\"Account has not opted out\\\");\\n\\n // Convert balance into the same amount at the current exchange rate\\n uint256 newCreditBalance = _creditBalances[msg.sender]\\n .mul(rebasingCreditsPerToken)\\n .div(_creditsPerToken(msg.sender));\\n\\n // Decreasing non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\\n\\n _creditBalances[msg.sender] = newCreditBalance;\\n\\n // Increase rebasing credits, totalSupply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\\n\\n rebaseState[msg.sender] = RebaseOptions.OptIn;\\n\\n // Delete any fixed credits per token\\n delete nonRebasingCreditsPerToken[msg.sender];\\n }\\n\\n /**\\n * @dev Remove a contract address to the non rebasing exception list.\\n */\\n function rebaseOptOut() public nonReentrant {\\n require(!_isNonRebasingAccount(msg.sender), \\\"Account has not opted in\\\");\\n\\n // Increase non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\\n // Set fixed credits per token\\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\\n\\n // Decrease rebasing credits, total supply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\\n\\n // Mark explicitly opted out of rebasing\\n rebaseState[msg.sender] = RebaseOptions.OptOut;\\n }\\n\\n /**\\n * @dev Modify the supply without minting new tokens. This uses a change in\\n * the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n * @return uint256 representing the new total supply.\\n */\\n function changeSupply(uint256 _newTotalSupply)\\n external\\n onlyVault\\n nonReentrant\\n {\\n require(_totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (_totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n return;\\n }\\n\\n _totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\\n _totalSupply.sub(nonRebasingSupply)\\n );\\n\\n require(rebasingCreditsPerToken > 0, \\\"Invalid change in supply\\\");\\n\\n _totalSupply = rebasingCredits\\n .divPrecisely(rebasingCreditsPerToken)\\n .add(nonRebasingSupply);\\n\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n }\\n}\\n\",\"keccak256\":\"0xea89a8b152b363982ba8db340b1e20c3194b2e75a06630cbbf43e3c50fff61a4\"},\"contracts/utils/Helpers.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0xd2ca92e0af883dc1aec5b22caced274e59829e0e30a9e955dcc48b8d921f5cdc\"},\"contracts/utils/InitializableERC20Detailed.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/**\\n * @dev Optional functions from the ERC20 standard.\\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\\n */\\ncontract InitializableERC20Detailed is IERC20 {\\n // Storage gap to skip storage from prior to OUSD reset\\n uint256[100] private _____gap;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\\n * these values are immutable: they can only be set once during\\n * construction.\\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\\n */\\n function _initialize(\\n string memory nameArg,\\n string memory symbolArg,\\n uint8 decimalsArg\\n ) internal {\\n _name = nameArg;\\n _symbol = symbolArg;\\n _decimals = decimalsArg;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view 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 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.\\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 returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x7919369d0f3bd74b4f0ee78a682afe43f91b186cdd0708e303068e4feeb29007\"},\"contracts/utils/StableMath.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n// Based on StableMath from Stability Labs Pty. Ltd.\\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\\n\\nlibrary StableMath {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Scaling unit for use in specific calculations,\\n * where 1 * 10**18, or 1e18 represents a unit '1'\\n */\\n uint256 private constant FULL_SCALE = 1e18;\\n\\n /***************************************\\n Helpers\\n ****************************************/\\n\\n /**\\n * @dev Adjust the scale of an integer\\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\\n */\\n function scaleBy(uint256 x, int8 adjustment)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (adjustment > 0) {\\n x = x.mul(10**uint256(adjustment));\\n } else if (adjustment < 0) {\\n x = x.div(10**uint256(adjustment * -1));\\n }\\n return x;\\n }\\n\\n /***************************************\\n Precise Arithmetic\\n ****************************************/\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\\n return mulTruncateScale(x, y, FULL_SCALE);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @param scale Scale unit\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncateScale(\\n uint256 x,\\n uint256 y,\\n uint256 scale\\n ) internal pure returns (uint256) {\\n // e.g. assume scale = fullScale\\n // z = 10e18 * 9e17 = 9e36\\n uint256 z = x.mul(y);\\n // return 9e38 / 1e18 = 9e18\\n return z.div(scale);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit, rounded up to the closest base unit.\\n */\\n function mulTruncateCeil(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e17 * 17268172638 = 138145381104e17\\n uint256 scaled = x.mul(y);\\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\\n return ceil.div(FULL_SCALE);\\n }\\n\\n /**\\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\\n * @param x Left hand input to division\\n * @param y Right hand input to division\\n * @return Result after multiplying the left operand by the scale, and\\n * executing the division on the right hand input.\\n */\\n function divPrecisely(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e18 * 1e18 = 8e36\\n uint256 z = x.mul(FULL_SCALE);\\n // e.g. 8e36 / 10e18 = 8e17\\n return z.div(y);\\n }\\n}\\n\",\"keccak256\":\"0xa77fccf850feb6d54ba3a6530f92554caef8a67a1ceb573d4f8a5d1bf64ff9d2\"},\"contracts/vault/VaultCore.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Vault Contract\\n * @notice The Vault contract stores assets. On a deposit, OUSD will be minted\\n and sent to the depositor. On a withdrawal, OUSD will be burned and\\n assets will be sent to the withdrawer. The Vault accepts deposits of\\n interest form yield bearing strategies which will modify the supply\\n of OUSD.\\n * @author Origin Protocol Inc\\n */\\n\\nimport \\\"./VaultStorage.sol\\\";\\nimport { IOracle } from \\\"../interfaces/IOracle.sol\\\";\\nimport { IVault } from \\\"../interfaces/IVault.sol\\\";\\nimport { IBuyback } from \\\"../interfaces/IBuyback.sol\\\";\\n\\ncontract VaultCore is VaultStorage {\\n uint256 constant MAX_UINT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\\n\\n /**\\n * @dev Verifies that the rebasing is not paused.\\n */\\n modifier whenNotRebasePaused() {\\n require(!rebasePaused, \\\"Rebasing paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Verifies that the deposits are not paused.\\n */\\n modifier whenNotCapitalPaused() {\\n require(!capitalPaused, \\\"Capital paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Deposit a supported asset and mint OUSD.\\n * @param _asset Address of the asset being deposited\\n * @param _amount Amount of the asset being deposited\\n * @param _minimumOusdAmount Minimum OUSD to mint\\n */\\n function mint(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external whenNotCapitalPaused nonReentrant {\\n require(assets[_asset].isSupported, \\\"Asset is not supported\\\");\\n require(_amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n uint256 price = IOracle(priceProvider).price(_asset);\\n if (price > 1e8) {\\n price = 1e8;\\n }\\n uint256 assetDecimals = Helpers.getDecimals(_asset);\\n uint256 unitAdjustedDeposit = _amount.scaleBy(int8(18 - assetDecimals));\\n uint256 priceAdjustedDeposit = _amount.mulTruncateScale(\\n price.scaleBy(int8(10)), // 18-8 because oracles have 8 decimals precision\\n 10**assetDecimals\\n );\\n\\n if (_minimumOusdAmount > 0) {\\n require(\\n priceAdjustedDeposit >= _minimumOusdAmount,\\n \\\"Mint amount lower than minimum\\\"\\n );\\n }\\n\\n emit Mint(msg.sender, priceAdjustedDeposit);\\n\\n // Rebase must happen before any transfers occur.\\n if (unitAdjustedDeposit >= rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n\\n // Mint matching OUSD\\n oUSD.mint(msg.sender, priceAdjustedDeposit);\\n\\n // Transfer the deposited coins to the vault\\n IERC20 asset = IERC20(_asset);\\n asset.safeTransferFrom(msg.sender, address(this), _amount);\\n\\n if (unitAdjustedDeposit >= autoAllocateThreshold) {\\n _allocate();\\n }\\n }\\n\\n /**\\n * @dev Mint for multiple assets in the same call.\\n * @param _assets Addresses of assets being deposited\\n * @param _amounts Amount of each asset at the same index in the _assets\\n * to deposit.\\n * @param _minimumOusdAmount Minimum OUSD to mint\\n */\\n function mintMultiple(\\n address[] calldata _assets,\\n uint256[] calldata _amounts,\\n uint256 _minimumOusdAmount\\n ) external whenNotCapitalPaused nonReentrant {\\n require(_assets.length == _amounts.length, \\\"Parameter length mismatch\\\");\\n\\n uint256 unitAdjustedTotal = 0;\\n uint256 priceAdjustedTotal = 0;\\n uint256[] memory assetPrices = _getAssetPrices(false);\\n for (uint256 j = 0; j < _assets.length; j++) {\\n // In memoriam\\n require(assets[_assets[j]].isSupported, \\\"Asset is not supported\\\");\\n require(_amounts[j] > 0, \\\"Amount must be greater than 0\\\");\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n if (_assets[j] == allAssets[i]) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n uint256 price = assetPrices[i];\\n if (price > 1e18) {\\n price = 1e18;\\n }\\n unitAdjustedTotal = unitAdjustedTotal.add(\\n _amounts[j].scaleBy(int8(18 - assetDecimals))\\n );\\n priceAdjustedTotal = priceAdjustedTotal.add(\\n _amounts[j].mulTruncateScale(price, 10**assetDecimals)\\n );\\n }\\n }\\n }\\n\\n if (_minimumOusdAmount > 0) {\\n require(\\n priceAdjustedTotal >= _minimumOusdAmount,\\n \\\"Mint amount lower than minimum\\\"\\n );\\n }\\n\\n emit Mint(msg.sender, priceAdjustedTotal);\\n\\n // Rebase must happen before any transfers occur.\\n if (unitAdjustedTotal >= rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n\\n oUSD.mint(msg.sender, priceAdjustedTotal);\\n\\n for (uint256 i = 0; i < _assets.length; i++) {\\n IERC20 asset = IERC20(_assets[i]);\\n asset.safeTransferFrom(msg.sender, address(this), _amounts[i]);\\n }\\n\\n if (unitAdjustedTotal >= autoAllocateThreshold) {\\n _allocate();\\n }\\n }\\n\\n /**\\n * @dev Withdraw a supported asset and burn OUSD.\\n * @param _amount Amount of OUSD to burn\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount)\\n public\\n whenNotCapitalPaused\\n nonReentrant\\n {\\n if (_amount > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n _redeem(_amount, _minimumUnitAmount);\\n }\\n\\n /**\\n * @dev Withdraw a supported asset and burn OUSD.\\n * @param _amount Amount of OUSD to burn\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function _redeem(uint256 _amount, uint256 _minimumUnitAmount) internal {\\n require(_amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n uint256 _totalSupply = oUSD.totalSupply();\\n uint256 _backingValue = _totalValue();\\n\\n if (maxSupplyDiff > 0) {\\n // Allow a max difference of maxSupplyDiff% between\\n // backing assets value and OUSD total supply\\n uint256 diff = _totalSupply.divPrecisely(_backingValue);\\n\\n require(\\n (diff > 1e18 ? diff.sub(1e18) : uint256(1e18).sub(diff)) <=\\n maxSupplyDiff,\\n \\\"Backing supply liquidity error\\\"\\n );\\n }\\n\\n emit Redeem(msg.sender, _amount);\\n\\n // Calculate redemption outputs\\n uint256[] memory outputs = _calculateRedeemOutputs(_amount);\\n // Send outputs\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n if (outputs[i] == 0) continue;\\n\\n IERC20 asset = IERC20(allAssets[i]);\\n\\n if (asset.balanceOf(address(this)) >= outputs[i]) {\\n // Use Vault funds first if sufficient\\n asset.safeTransfer(msg.sender, outputs[i]);\\n } else {\\n address strategyAddr = assetDefaultStrategies[allAssets[i]];\\n if (strategyAddr != address(0)) {\\n // Nothing in Vault, but something in Strategy, send from there\\n IStrategy strategy = IStrategy(strategyAddr);\\n strategy.withdraw(msg.sender, allAssets[i], outputs[i]);\\n } else {\\n // Cant find funds anywhere\\n revert(\\\"Liquidity error\\\");\\n }\\n }\\n }\\n\\n if (_minimumUnitAmount > 0) {\\n uint256 unitTotal = 0;\\n for (uint256 i = 0; i < outputs.length; i++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n unitTotal = unitTotal.add(\\n outputs[i].scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n require(\\n unitTotal >= _minimumUnitAmount,\\n \\\"Redeem amount lower than minimum\\\"\\n );\\n }\\n\\n oUSD.burn(msg.sender, _amount);\\n\\n // Until we can prove that we won't affect the prices of our assets\\n // by withdrawing them, this should be here.\\n // It's possible that a strategy was off on its asset total, perhaps\\n // a reward token sold for more or for less than anticipated.\\n if (_amount > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n }\\n\\n /**\\n * @notice Withdraw a supported asset and burn all OUSD.\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function redeemAll(uint256 _minimumUnitAmount)\\n external\\n whenNotCapitalPaused\\n nonReentrant\\n {\\n // Unfortunately we have to do balanceOf twice, the rebase may change\\n // the account balance\\n if (oUSD.balanceOf(msg.sender) > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n _redeem(oUSD.balanceOf(msg.sender), _minimumUnitAmount);\\n }\\n\\n /**\\n * @notice Allocate unallocated funds on Vault to strategies.\\n * @dev Allocate unallocated funds on Vault to strategies.\\n **/\\n function allocate() public whenNotCapitalPaused nonReentrant {\\n _allocate();\\n }\\n\\n /**\\n * @notice Allocate unallocated funds on Vault to strategies.\\n * @dev Allocate unallocated funds on Vault to strategies.\\n **/\\n function _allocate() internal {\\n uint256 vaultValue = _totalValueInVault();\\n // Nothing in vault to allocate\\n if (vaultValue == 0) return;\\n uint256 strategiesValue = _totalValueInStrategies();\\n // We have a method that does the same as this, gas optimisation\\n uint256 calculatedTotalValue = vaultValue.add(strategiesValue);\\n\\n // We want to maintain a buffer on the Vault so calculate a percentage\\n // modifier to multiply each amount being allocated by to enforce the\\n // vault buffer\\n uint256 vaultBufferModifier;\\n if (strategiesValue == 0) {\\n // Nothing in Strategies, allocate 100% minus the vault buffer to\\n // strategies\\n vaultBufferModifier = uint256(1e18).sub(vaultBuffer);\\n } else {\\n vaultBufferModifier = vaultBuffer.mul(calculatedTotalValue).div(\\n vaultValue\\n );\\n if (1e18 > vaultBufferModifier) {\\n // E.g. 1e18 - (1e17 * 10e18)/5e18 = 8e17\\n // (5e18 * 8e17) / 1e18 = 4e18 allocated from Vault\\n vaultBufferModifier = uint256(1e18).sub(vaultBufferModifier);\\n } else {\\n // We need to let the buffer fill\\n return;\\n }\\n }\\n if (vaultBufferModifier == 0) return;\\n\\n // Iterate over all assets in the Vault and allocate the the appropriate\\n // strategy\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n IERC20 asset = IERC20(allAssets[i]);\\n uint256 assetBalance = asset.balanceOf(address(this));\\n // No balance, nothing to do here\\n if (assetBalance == 0) continue;\\n\\n // Multiply the balance by the vault buffer modifier and truncate\\n // to the scale of the asset decimals\\n uint256 allocateAmount = assetBalance.mulTruncate(\\n vaultBufferModifier\\n );\\n\\n address depositStrategyAddr = assetDefaultStrategies[address(\\n asset\\n )];\\n\\n if (depositStrategyAddr != address(0) && allocateAmount > 0) {\\n IStrategy strategy = IStrategy(depositStrategyAddr);\\n // Transfer asset to Strategy and call deposit method to\\n // mint or take required action\\n asset.safeTransfer(address(strategy), allocateAmount);\\n strategy.deposit(address(asset), allocateAmount);\\n }\\n }\\n\\n // Harvest for all reward tokens above reward liquidation threshold\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n address rewardTokenAddress = strategy.rewardTokenAddress();\\n if (rewardTokenAddress != address(0)) {\\n uint256 liquidationThreshold = strategy\\n .rewardLiquidationThreshold();\\n if (liquidationThreshold == 0) {\\n // No threshold set, always harvest from strategy\\n IVault(address(this)).harvest(allStrategies[i]);\\n } else {\\n // Check balance against liquidation threshold\\n // Note some strategies don't hold the reward token balance\\n // on their contract so the liquidation threshold should be\\n // set to 0\\n IERC20 rewardToken = IERC20(rewardTokenAddress);\\n uint256 rewardTokenAmount = rewardToken.balanceOf(\\n allStrategies[i]\\n );\\n if (rewardTokenAmount >= liquidationThreshold) {\\n IVault(address(this)).harvest(allStrategies[i]);\\n }\\n }\\n }\\n }\\n\\n // Trigger OGN Buyback\\n IBuyback(trusteeAddress).swap();\\n }\\n\\n /**\\n * @dev Calculate the total value of assets held by the Vault and all\\n * strategies and update the supply of OUSD.\\n */\\n function rebase() public whenNotRebasePaused nonReentrant {\\n _rebase();\\n }\\n\\n /**\\n * @dev Calculate the total value of assets held by the Vault and all\\n * strategies and update the supply of OUSD, optionaly sending a\\n * portion of the yield to the trustee.\\n */\\n function _rebase() internal whenNotRebasePaused {\\n uint256 ousdSupply = oUSD.totalSupply();\\n if (ousdSupply == 0) {\\n return;\\n }\\n uint256 vaultValue = _totalValue();\\n\\n // Yield fee collection\\n address _trusteeAddress = trusteeAddress; // gas savings\\n if (_trusteeAddress != address(0) && (vaultValue > ousdSupply)) {\\n uint256 yield = vaultValue.sub(ousdSupply);\\n uint256 fee = yield.mul(trusteeFeeBps).div(10000);\\n require(yield > fee, \\\"Fee must not be greater than yield\\\");\\n if (fee > 0) {\\n oUSD.mint(_trusteeAddress, fee);\\n }\\n emit YieldDistribution(_trusteeAddress, yield, fee);\\n }\\n\\n // Only rachet OUSD supply upwards\\n ousdSupply = oUSD.totalSupply(); // Final check should use latest value\\n if (vaultValue > ousdSupply) {\\n oUSD.changeSupply(vaultValue);\\n }\\n }\\n\\n /**\\n * @dev Determine the total value of assets held by the vault and its\\n * strategies.\\n * @return uint256 value Total value in USD (1e18)\\n */\\n function totalValue() external view returns (uint256 value) {\\n value = _totalValue();\\n }\\n\\n /**\\n * @dev Internal Calculate the total value of the assets held by the\\n * vault and its strategies.\\n * @return uint256 value Total value in USD (1e18)\\n */\\n function _totalValue() internal view returns (uint256 value) {\\n return _totalValueInVault().add(_totalValueInStrategies());\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held in Vault.\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInVault() internal view returns (uint256 value) {\\n for (uint256 y = 0; y < allAssets.length; y++) {\\n IERC20 asset = IERC20(allAssets[y]);\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\\n uint256 balance = asset.balanceOf(address(this));\\n if (balance > 0) {\\n value = value.add(balance.scaleBy(int8(18 - assetDecimals)));\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held in Strategies.\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInStrategies() internal view returns (uint256 value) {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n value = value.add(_totalValueInStrategy(allStrategies[i]));\\n }\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held by strategy.\\n * @param _strategyAddr Address of the strategy\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInStrategy(address _strategyAddr)\\n internal\\n view\\n returns (uint256 value)\\n {\\n IStrategy strategy = IStrategy(_strategyAddr);\\n for (uint256 y = 0; y < allAssets.length; y++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\\n if (strategy.supportsAsset(allAssets[y])) {\\n uint256 balance = strategy.checkBalance(allAssets[y]);\\n if (balance > 0) {\\n value = value.add(\\n balance.scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Get the balance of an asset held in Vault and all strategies.\\n * @param _asset Address of asset\\n * @return uint256 Balance of asset in decimals of asset\\n */\\n function checkBalance(address _asset) external view returns (uint256) {\\n return _checkBalance(_asset);\\n }\\n\\n /**\\n * @notice Get the balance of an asset held in Vault and all strategies.\\n * @param _asset Address of asset\\n * @return uint256 Balance of asset in decimals of asset\\n */\\n function _checkBalance(address _asset)\\n internal\\n view\\n returns (uint256 balance)\\n {\\n IERC20 asset = IERC20(_asset);\\n balance = asset.balanceOf(address(this));\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n if (strategy.supportsAsset(_asset)) {\\n balance = balance.add(strategy.checkBalance(_asset));\\n }\\n }\\n }\\n\\n /**\\n * @notice Get the balance of all assets held in Vault and all strategies.\\n * @return uint256 Balance of all assets (1e18)\\n */\\n function _checkBalance() internal view returns (uint256 balance) {\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n balance = balance.add(\\n _checkBalance(allAssets[i]).scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n }\\n\\n /**\\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\\n * coins that will be returned\\n */\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory)\\n {\\n return _calculateRedeemOutputs(_amount);\\n }\\n\\n /**\\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\\n * coins that will be returned.\\n * @return Array of amounts respective to the supported assets\\n */\\n function _calculateRedeemOutputs(uint256 _amount)\\n internal\\n view\\n returns (uint256[] memory outputs)\\n {\\n // We always give out coins in proportion to how many we have,\\n // Now if all coins were the same value, this math would easy,\\n // just take the percentage of each coin, and multiply by the\\n // value to be given out. But if coins are worth more than $1,\\n // then we would end up handing out too many coins. We need to\\n // adjust by the total value of coins.\\n //\\n // To do this, we total up the value of our coins, by their\\n // percentages. Then divide what we would otherwise give out by\\n // this number.\\n //\\n // Let say we have 100 DAI at $1.06 and 200 USDT at $1.00.\\n // So for every 1 DAI we give out, we'll be handing out 2 USDT\\n // Our total output ratio is: 33% * 1.06 + 66% * 1.00 = 1.02\\n //\\n // So when calculating the output, we take the percentage of\\n // each coin, times the desired output value, divided by the\\n // totalOutputRatio.\\n //\\n // For example, withdrawing: 30 OUSD:\\n // DAI 33% * 30 / 1.02 = 9.80 DAI\\n // USDT = 66 % * 30 / 1.02 = 19.60 USDT\\n //\\n // Checking these numbers:\\n // 9.80 DAI * 1.06 = $10.40\\n // 19.60 USDT * 1.00 = $19.60\\n //\\n // And so the user gets $10.40 + $19.60 = $30 worth of value.\\n\\n uint256 assetCount = getAssetCount();\\n uint256[] memory assetPrices = _getAssetPrices(true);\\n uint256[] memory assetBalances = new uint256[](assetCount);\\n uint256[] memory assetDecimals = new uint256[](assetCount);\\n uint256 totalBalance = 0;\\n uint256 totalOutputRatio = 0;\\n outputs = new uint256[](assetCount);\\n\\n // Calculate redeem fee\\n if (redeemFeeBps > 0) {\\n uint256 redeemFee = _amount.mul(redeemFeeBps).div(10000);\\n _amount = _amount.sub(redeemFee);\\n }\\n\\n // Calculate assets balances and decimals once,\\n // for a large gas savings.\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 balance = _checkBalance(allAssets[i]);\\n uint256 decimals = Helpers.getDecimals(allAssets[i]);\\n assetBalances[i] = balance;\\n assetDecimals[i] = decimals;\\n totalBalance = totalBalance.add(\\n balance.scaleBy(int8(18 - decimals))\\n );\\n }\\n // Calculate totalOutputRatio\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 price = assetPrices[i];\\n // Never give out more than one\\n // stablecoin per dollar of OUSD\\n if (price < 1e18) {\\n price = 1e18;\\n }\\n uint256 ratio = assetBalances[i]\\n .scaleBy(int8(18 - assetDecimals[i]))\\n .mul(price)\\n .div(totalBalance);\\n totalOutputRatio = totalOutputRatio.add(ratio);\\n }\\n // Calculate final outputs\\n uint256 factor = _amount.divPrecisely(totalOutputRatio);\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n outputs[i] = assetBalances[i].mul(factor).div(totalBalance);\\n }\\n }\\n\\n /**\\n * @notice Get an array of the supported asset prices in USD.\\n * @return uint256[] Array of asset prices in USD (1e18)\\n */\\n function _getAssetPrices(bool useMax)\\n internal\\n view\\n returns (uint256[] memory assetPrices)\\n {\\n assetPrices = new uint256[](getAssetCount());\\n\\n IOracle oracle = IOracle(priceProvider);\\n // Price from Oracle is returned with 8 decimals\\n // _amount is in assetDecimals\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n assetPrices[i] = oracle.price(allAssets[i]).scaleBy(int8(18 - 8));\\n }\\n }\\n\\n /***************************************\\n Utils\\n ****************************************/\\n\\n /**\\n * @dev Return the number of assets suppported by the Vault.\\n */\\n function getAssetCount() public view returns (uint256) {\\n return allAssets.length;\\n }\\n\\n /**\\n * @dev Return all asset addresses in order\\n */\\n function getAllAssets() external view returns (address[] memory) {\\n return allAssets;\\n }\\n\\n /**\\n * @dev Return the number of strategies active on the Vault.\\n */\\n function getStrategyCount() external view returns (uint256) {\\n return allStrategies.length;\\n }\\n\\n function isSupportedAsset(address _asset) external view returns (bool) {\\n return assets[_asset].isSupported;\\n }\\n\\n /**\\n * @dev Falldown to the admin implementation\\n * @notice This is a catch all for all functions not declared in core\\n */\\n function() external payable {\\n bytes32 slot = adminImplPosition;\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize)\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas, sload(slot), 0, calldatasize, 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize)\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize)\\n }\\n default {\\n return(0, returndatasize)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7dff24efb502d476c147d671bb4080a596fe020dbf9f7b2643fc4eb2f1061717\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD VaultStorage Contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\n\\ncontract VaultStorage is Initializable, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n using SafeMath for int256;\\n using SafeERC20 for IERC20;\\n\\n event AssetSupported(address _asset);\\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\\n event PriceProviderUpdated(address _priceProvider);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event UniswapUpdated(address _address);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n\\n // Assets supported by the Vault, i.e. Stablecoins\\n struct Asset {\\n bool isSupported;\\n }\\n mapping(address => Asset) assets;\\n address[] allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n mapping(address => Strategy) strategies;\\n address[] allStrategies;\\n\\n // Address of the Oracle price provider contract\\n address public priceProvider;\\n // Pausing bools\\n bool public rebasePaused = false;\\n bool public capitalPaused = true;\\n // Redemption fee in basis points\\n uint256 public redeemFeeBps;\\n // Buffer of assets to keep in Vault to handle (most) withdrawals\\n uint256 public vaultBuffer;\\n // Mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n // Mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n OUSD oUSD;\\n\\n //keccak256(\\\"OUSD.vault.governor.admin.impl\\\");\\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\\n\\n // Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n // Address of Uniswap\\n address public uniswapAddr = address(0);\\n\\n // Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n // Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n mapping(address => address) public assetDefaultStrategies;\\n\\n uint256 public maxSupplyDiff;\\n\\n // Trustee contract that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n // Amount of yield collected in basis points\\n uint256 public trusteeFeeBps;\\n\\n /**\\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\\n * @param newImpl address of the implementation\\n */\\n function setAdminImpl(address newImpl) external onlyGovernor {\\n require(\\n Address.isContract(newImpl),\\n \\\"new implementation is not a contract\\\"\\n );\\n bytes32 position = adminImplPosition;\\n assembly {\\n sstore(position, newImpl)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc945fa95b0fb31ae523cf91bd89bbf1289de38b02a8b082b98fed152c00c7746\"}},\"version\":1}", + "bytecode": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b600080516020620037d383398151915255565b600080516020620037d38339815191525490565b6136e180620000f26000396000f3fe6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610ad1565b3480156102ed57600080fd5b50610233610ad7565b34801561030257600080fd5b5061030b610add565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610b3f565b34801561037c57600080fd5b5061025a610b45565b34801561039157600080fd5b50610233610b54565b3480156103a657600080fd5b506103af610b5a565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610b6a565b3480156103e457600080fd5b506102ca610b79565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610bdb565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610bec565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610bf7565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610dc7565b3480156104b057600080fd5b50610233610eae565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610eb4565b3480156104f857600080fd5b50610233610ed2565b34801561050d57600080fd5b50610233610ed8565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610ede565b34801561055557600080fd5b506102ca610ef9565b34801561056a57600080fd5b506102ca610fb4565b34801561057f57600080fd5b5061025a611069565b34801561059457600080fd5b506103af611078565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b031661109b565b3480156105dc57600080fd5b50610233611147565b3480156105f157600080fd5b506103af611151565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b919350915035611161565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b031661165c565b60385481565b600061070c61171d565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a3833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603754604080516315d5220f60e31b81526001600160a01b0388811660048301529151600093929092169163aea9107891602480820192602092909190829003018186803b1580156108d857600080fd5b505afa1580156108ec573d6000803e3d6000fd5b505050506040513d602081101561090257600080fd5b505190506305f5e10081111561091957506305f5e1005b600061092487611742565b9050600061093c87601284900363ffffffff6117fc16565b9050600061096661095485600a63ffffffff6117fc16565b8990600a86900a63ffffffff61185616565b905086156109c357868110156109c3576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a1a5750603754600160a01b900460ff16155b15610a2757610a27611884565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b508b9250610ab09150506001600160a01b03821633308c63ffffffff611bab16565b603a548310610ac157610ac1611c0b565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b3557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b17575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610b81612196565b6001600160a01b0316336001600160a01b031614610bd05760405162461bcd60e51b815260040180806020018281038252603081526020018061367d6030913960400191505060405180910390fd5b610bd9336121bb565b565b6000610be682612269565b92915050565b6060610be68261242a565b603754600160a81b900460ff1615610c47576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610c9f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b54603c54604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610cf157600080fd5b505afa158015610d05573d6000803e3d6000fd5b505050506040513d6020811015610d1b57600080fd5b5051118015610d345750603754600160a01b900460ff16155b15610d4157610d41611884565b603c54604080516370a0823160e01b81523360048201529051610dbf926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610d8d57600080fd5b505afa158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b5051846126eb565b506001905550565b603754600160a81b900460ff1615610e17576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610e6f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b5484118015610e8e5750603754600160a01b900460ff16155b15610e9b57610e9b611884565b610ea584846126eb565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610f49576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610fa1576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610fad611c0b565b5060019055565b603754600160a01b900460ff1615611005576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206135a38339815191528054600281141561105d576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610fad611884565b6037546001600160a01b031681565b600061108261171d565b6001600160a01b0316336001600160a01b031614905090565b6110a3611078565b6110f4576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6110fd81612c9c565b806001600160a01b031661110f61171d565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612cc0565b603754600160a81b900460ff1681565b603754600160a81b900460ff16156111b1576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415611209576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255858414611261576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b600080606061126f82612ce1565b905060005b898110156114a857603360008c8c8481811061128c57fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166112fc576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061130a57fe5b9050602002013511611363576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b60345481101561149f576034818154811061137d57fe5b6000918252602090912001546001600160a01b03168c8c8481811061139e57fe5b905060200201356001600160a01b03166001600160a01b031614156114975760006113e9603483815481106113cf57fe5b6000918252602090912001546001600160a01b0316611742565b905060008483815181106113f957fe5b60200260200101519050670de0b6b3a764000081111561141e5750670de0b6b3a76400005b611456611449836012038e8e8881811061143457fe5b905060200201356117fc90919063ffffffff16565b889063ffffffff612df716565b96506114926114858284600a0a8f8f8981811061146f57fe5b905060200201356118569092919063ffffffff16565b879063ffffffff612df716565b955050505b600101611366565b50600101611274565b5085156115045785821015611504576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b54831015801561155b5750603754600160a01b900460ff16155b1561156857611568611884565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b1580156115bb57600080fd5b505af11580156115cf573d6000803e3d6000fd5b506000925050505b8981101561163a5760008b8b838181106115ed57fe5b905060200201356001600160a01b0316905061163133308c8c8681811061161057fe5b90506020020135846001600160a01b0316611bab909392919063ffffffff16565b506001016115d7565b50603a54831061164c5761164c611c0b565b5050506001825550505050505050565b611664611078565b6116b5576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6116be81612e58565b6116f95760405162461bcd60e51b81526004018080602001828103825260248152602001806135c36024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561177e57600080fd5b505afa158015611792573d6000803e3d6000fd5b505050506040513d60208110156117a857600080fd5b505160ff169050600481108015906117c1575060128111155b610be65760405162461bcd60e51b81526004018080602001828103825260298152602001806135e76029913960400191505060405180910390fd5b6000808260000b13156118275761182083600084900b600a0a63ffffffff612e9416565b925061184f565b60008260000b121561184f5761184c836000848103900b600a0a63ffffffff612eed16565b92505b5090919050565b600080611869858563ffffffff612e9416565b905061187b818463ffffffff612eed16565b95945050505050565b603754600160a01b900460ff16156118d5576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561191a57600080fd5b505afa15801561192e573d6000803e3d6000fd5b505050506040513d602081101561194457600080fd5b50519050806119535750610bd9565b600061195d612cc0565b6042549091506001600160a01b0316801580159061197a57508282115b15611abc576000611991838563ffffffff612f2f16565b905060006119bc6127106119b060435485612e9490919063ffffffff16565b9063ffffffff612eed16565b90508082116119fc5760405162461bcd60e51b81526004018080602001828103825260228152602001806136316022913960400191505060405180910390fd5b8015611a7057603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611a5757600080fd5b505af1158015611a6b573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0a57600080fd5b505afa158015611b1e573d6000803e3d6000fd5b505050506040513d6020811015611b3457600080fd5b5051925082821115611ba657603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611b8d57600080fd5b505af1158015611ba1573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611c05908590612f71565b50505050565b6000611c15613129565b905080611c225750610bd9565b6000611c2c613219565b90506000611c40838363ffffffff612df716565b9050600082611c6c57603954611c6590670de0b6b3a76400009063ffffffff612f2f16565b9050611cb8565b611c85846119b084603954612e9490919063ffffffff16565b905080670de0b6b3a76400001115611caf57611c65670de0b6b3a76400008263ffffffff612f2f16565b50505050610bd9565b80611cc65750505050610bd9565b60005b603454811015611e5557600060348281548110611ce257fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611d3557600080fd5b505afa158015611d49573d6000803e3d6000fd5b505050506040513d6020811015611d5f57600080fd5b5051905080611d6f575050611e4d565b6000611d81828663ffffffff61326b16565b6001600160a01b03808516600090815260406020819052902054919250168015801590611dae5750600082115b15611e485780611dce6001600160a01b038616828563ffffffff61328016565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611e2e57600080fd5b505af1158015611e42573d6000803e3d6000fd5b50505050505b505050505b600101611cc9565b5060005b60365481101561212757600060368281548110611e7257fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b158015611ebf57600080fd5b505afa158015611ed3573d6000803e3d6000fd5b505050506040513d6020811015611ee957600080fd5b505190506001600160a01b0381161561211d576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b5051905080611ff057306001600160a01b0316630e5c011e60368681548110611f8657fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b5050505061211b565b60008290506000816001600160a01b03166370a082316036888154811061201357fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561206157600080fd5b505afa158015612075573d6000803e3d6000fd5b505050506040513d602081101561208b57600080fd5b5051905082811061211857306001600160a01b0316630e5c011e603688815481106120b257fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b1580156120ff57600080fd5b505af1158015612113573d6000803e3d6000fd5b505050505b50505b505b5050600101611e59565b50604260009054906101000a90046001600160a01b03166001600160a01b0316638119c0656040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561217857600080fd5b505af115801561218c573d6000803e3d6000fd5b5050505050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116612216576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661222861171d565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3612266816132d2565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156122b457600080fd5b505afa1580156122c8573d6000803e3d6000fd5b505050506040513d60208110156122de57600080fd5b5051915060005b603654811015612423576000603682815481106122fe57fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561235457600080fd5b505afa158015612368573d6000803e3d6000fd5b505050506040513d602081101561237e57600080fd5b50511561241a57612417816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156123de57600080fd5b505afa1580156123f2573d6000803e3d6000fd5b505050506040513d602081101561240857600080fd5b5051859063ffffffff612df716565b93505b506001016122e5565b5050919050565b60606000612436610ed8565b905060606124446001612ce1565b9050606082604051908082528060200260200182016040528015612472578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156124a1578160200160208202803883390190505b5060408051868152602080880282010190915290915060009081908680156124d3578160200160208202803883390190505b50603854909750156125125760006124fc6127106119b06038548c612e9490919063ffffffff16565b905061250e898263ffffffff612f2f16565b9850505b60005b6034548110156125c257600061254b6034838154811061253157fe5b6000918252602090912001546001600160a01b0316612269565b9050600061255f603484815481106113cf57fe5b90508187848151811061256e57fe5b6020026020010181815250508086848151811061258757fe5b60209081029190910101526125b66125a983601284900363ffffffff6117fc16565b869063ffffffff612df716565b94505050600101612515565b5060005b6034548110156126735760008682815181106125de57fe5b60200260200101519050670de0b6b3a76400008110156126035750670de0b6b3a76400005b6000612655856119b0846126498a888151811061261c57fe5b60200260200101516012038c898151811061263357fe5b60200260200101516117fc90919063ffffffff16565b9063ffffffff612e9416565b9050612667848263ffffffff612df716565b935050506001016125c6565b506000612686898363ffffffff6132f616565b905060005b6034548110156126de576126bf846119b0848985815181106126a957fe5b6020026020010151612e9490919063ffffffff16565b8982815181106126cb57fe5b602090810291909101015260010161268b565b5050505050505050919050565b60008211612740576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561278557600080fd5b505afa158015612799573d6000803e3d6000fd5b505050506040513d60208110156127af57600080fd5b5051905060006127bd612cc0565b604154909150156128785760006127da838363ffffffff6132f616565b9050604154670de0b6b3a7640000821161280b57612806670de0b6b3a76400008363ffffffff612f2f16565b612823565b61282382670de0b6b3a764000063ffffffff612f2f16565b1115612876576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810186905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160606128be8561242a565b905060005b603454811015612b54578181815181106128d957fe5b6020026020010151600014156128ee57612b4c565b6000603482815481106128fd57fe5b60009182526020909120015483516001600160a01b03909116915083908390811061292457fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b5051106129e9576129e4338484815181106129c357fe5b6020026020010151836001600160a01b03166132809092919063ffffffff16565b612b4a565b600060406000603485815481106129fc57fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612b09576000819050806001600160a01b031663d9caed123360348781548110612a5157fe5b9060005260206000200160009054906101000a90046001600160a01b0316888881518110612a7b57fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612aeb57600080fd5b505af1158015612aff573d6000803e3d6000fd5b5050505050612b48565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b6001016128c3565b508315612c02576000805b8251811015612baa576000612b7a603483815481106113cf57fe5b9050612b9f612b928260120386858151811061263357fe5b849063ffffffff612df716565b925050600101612b5f565b5084811015612c00576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612c5557600080fd5b505af1158015612c69573d6000803e3d6000fd5b50505050603b5485118015612c885750603754600160a01b900460ff16155b15612c9557612c95611884565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612ccd613219565b612cd5613129565b9063ffffffff612df716565b6060612ceb610ed8565b604051908082528060200260200182016040528015612d14578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561242357612dd8600a836001600160a01b031663aea9107860348581548110612d5257fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015612da057600080fd5b505afa158015612db4573d6000803e3d6000fd5b505050506040513d6020811015612dca57600080fd5b50519063ffffffff6117fc16565b838281518110612de457fe5b6020908102919091010152600101612d27565b600082820183811015612e51576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612e8c57508115155b949350505050565b600082612ea357506000610be6565b82820282848281612eb057fe5b0414612e515760405162461bcd60e51b81526004018080602001828103825260218152602001806136106021913960400191505060405180910390fd5b6000612e5183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613323565b6000612e5183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506133c5565b612f83826001600160a01b0316612e58565b612fd4576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106130125780518252601f199092019160209182019101612ff3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613074576040519150601f19603f3d011682016040523d82523d6000602084013e613079565b606091505b5091509150816130d0576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611c05578080602001905160208110156130ec57600080fd5b5051611c055760405162461bcd60e51b815260040180806020018281038252602a815260200180613653602a913960400191505060405180910390fd5b6000805b6034548110156132155760006034828154811061314657fe5b6000918252602082200154603480546001600160a01b03909216935061317091859081106113cf57fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156131bc57600080fd5b505afa1580156131d0573d6000803e3d6000fd5b505050506040513d60208110156131e657600080fd5b50519050801561320a576132076125a982601285900363ffffffff6117fc16565b94505b50505060010161312d565b5090565b6000805b603654811015613215576132616132546036838154811061323a57fe5b6000918252602090912001546001600160a01b031661341f565b839063ffffffff612df716565b915060010161321d565b6000612e518383670de0b6b3a7640000611856565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611ba6908490612f71565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061331184670de0b6b3a764000063ffffffff612e9416565b9050612e8c818463ffffffff612eed16565b600081836133af5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561337457818101518382015260200161335c565b50505050905090810190601f1680156133a15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816133bb57fe5b0495945050505050565b600081848411156134175760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561337457818101518382015260200161335c565b505050900390565b600081815b603454811015612423576000613440603483815481106113cf57fe5b9050826001600160a01b031663aa388af66034848154811061345e57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156134ac57600080fd5b505afa1580156134c0573d6000803e3d6000fd5b505050506040513d60208110156134d657600080fd5b505115613599576000836001600160a01b0316635f515226603485815481106134fb57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561354957600080fd5b505afa15801561355d573d6000803e3d6000fd5b505050506040513d602081101561357357600080fd5b505190508015613597576135946125a982601285900363ffffffff6117fc16565b94505b505b5060010161342456fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820f5ce484058ce120d7bb6fefde3051498b9396da8f85e58bb4fb70cd2ed9251b264736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610ad1565b3480156102ed57600080fd5b50610233610ad7565b34801561030257600080fd5b5061030b610add565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610b3f565b34801561037c57600080fd5b5061025a610b45565b34801561039157600080fd5b50610233610b54565b3480156103a657600080fd5b506103af610b5a565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610b6a565b3480156103e457600080fd5b506102ca610b79565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610bdb565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610bec565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610bf7565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610dc7565b3480156104b057600080fd5b50610233610eae565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610eb4565b3480156104f857600080fd5b50610233610ed2565b34801561050d57600080fd5b50610233610ed8565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610ede565b34801561055557600080fd5b506102ca610ef9565b34801561056a57600080fd5b506102ca610fb4565b34801561057f57600080fd5b5061025a611069565b34801561059457600080fd5b506103af611078565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b031661109b565b3480156105dc57600080fd5b50610233611147565b3480156105f157600080fd5b506103af611151565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b919350915035611161565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b031661165c565b60385481565b600061070c61171d565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a3833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603754604080516315d5220f60e31b81526001600160a01b0388811660048301529151600093929092169163aea9107891602480820192602092909190829003018186803b1580156108d857600080fd5b505afa1580156108ec573d6000803e3d6000fd5b505050506040513d602081101561090257600080fd5b505190506305f5e10081111561091957506305f5e1005b600061092487611742565b9050600061093c87601284900363ffffffff6117fc16565b9050600061096661095485600a63ffffffff6117fc16565b8990600a86900a63ffffffff61185616565b905086156109c357868110156109c3576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a1a5750603754600160a01b900460ff16155b15610a2757610a27611884565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b508b9250610ab09150506001600160a01b03821633308c63ffffffff611bab16565b603a548310610ac157610ac1611c0b565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b3557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b17575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610b81612196565b6001600160a01b0316336001600160a01b031614610bd05760405162461bcd60e51b815260040180806020018281038252603081526020018061367d6030913960400191505060405180910390fd5b610bd9336121bb565b565b6000610be682612269565b92915050565b6060610be68261242a565b603754600160a81b900460ff1615610c47576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610c9f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b54603c54604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610cf157600080fd5b505afa158015610d05573d6000803e3d6000fd5b505050506040513d6020811015610d1b57600080fd5b5051118015610d345750603754600160a01b900460ff16155b15610d4157610d41611884565b603c54604080516370a0823160e01b81523360048201529051610dbf926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610d8d57600080fd5b505afa158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b5051846126eb565b506001905550565b603754600160a81b900460ff1615610e17576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610e6f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b5484118015610e8e5750603754600160a01b900460ff16155b15610e9b57610e9b611884565b610ea584846126eb565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610f49576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610fa1576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610fad611c0b565b5060019055565b603754600160a01b900460ff1615611005576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206135a38339815191528054600281141561105d576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610fad611884565b6037546001600160a01b031681565b600061108261171d565b6001600160a01b0316336001600160a01b031614905090565b6110a3611078565b6110f4576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6110fd81612c9c565b806001600160a01b031661110f61171d565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612cc0565b603754600160a81b900460ff1681565b603754600160a81b900460ff16156111b1576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415611209576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255858414611261576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b600080606061126f82612ce1565b905060005b898110156114a857603360008c8c8481811061128c57fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166112fc576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061130a57fe5b9050602002013511611363576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b60345481101561149f576034818154811061137d57fe5b6000918252602090912001546001600160a01b03168c8c8481811061139e57fe5b905060200201356001600160a01b03166001600160a01b031614156114975760006113e9603483815481106113cf57fe5b6000918252602090912001546001600160a01b0316611742565b905060008483815181106113f957fe5b60200260200101519050670de0b6b3a764000081111561141e5750670de0b6b3a76400005b611456611449836012038e8e8881811061143457fe5b905060200201356117fc90919063ffffffff16565b889063ffffffff612df716565b96506114926114858284600a0a8f8f8981811061146f57fe5b905060200201356118569092919063ffffffff16565b879063ffffffff612df716565b955050505b600101611366565b50600101611274565b5085156115045785821015611504576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b54831015801561155b5750603754600160a01b900460ff16155b1561156857611568611884565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b1580156115bb57600080fd5b505af11580156115cf573d6000803e3d6000fd5b506000925050505b8981101561163a5760008b8b838181106115ed57fe5b905060200201356001600160a01b0316905061163133308c8c8681811061161057fe5b90506020020135846001600160a01b0316611bab909392919063ffffffff16565b506001016115d7565b50603a54831061164c5761164c611c0b565b5050506001825550505050505050565b611664611078565b6116b5576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6116be81612e58565b6116f95760405162461bcd60e51b81526004018080602001828103825260248152602001806135c36024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561177e57600080fd5b505afa158015611792573d6000803e3d6000fd5b505050506040513d60208110156117a857600080fd5b505160ff169050600481108015906117c1575060128111155b610be65760405162461bcd60e51b81526004018080602001828103825260298152602001806135e76029913960400191505060405180910390fd5b6000808260000b13156118275761182083600084900b600a0a63ffffffff612e9416565b925061184f565b60008260000b121561184f5761184c836000848103900b600a0a63ffffffff612eed16565b92505b5090919050565b600080611869858563ffffffff612e9416565b905061187b818463ffffffff612eed16565b95945050505050565b603754600160a01b900460ff16156118d5576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561191a57600080fd5b505afa15801561192e573d6000803e3d6000fd5b505050506040513d602081101561194457600080fd5b50519050806119535750610bd9565b600061195d612cc0565b6042549091506001600160a01b0316801580159061197a57508282115b15611abc576000611991838563ffffffff612f2f16565b905060006119bc6127106119b060435485612e9490919063ffffffff16565b9063ffffffff612eed16565b90508082116119fc5760405162461bcd60e51b81526004018080602001828103825260228152602001806136316022913960400191505060405180910390fd5b8015611a7057603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611a5757600080fd5b505af1158015611a6b573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0a57600080fd5b505afa158015611b1e573d6000803e3d6000fd5b505050506040513d6020811015611b3457600080fd5b5051925082821115611ba657603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611b8d57600080fd5b505af1158015611ba1573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611c05908590612f71565b50505050565b6000611c15613129565b905080611c225750610bd9565b6000611c2c613219565b90506000611c40838363ffffffff612df716565b9050600082611c6c57603954611c6590670de0b6b3a76400009063ffffffff612f2f16565b9050611cb8565b611c85846119b084603954612e9490919063ffffffff16565b905080670de0b6b3a76400001115611caf57611c65670de0b6b3a76400008263ffffffff612f2f16565b50505050610bd9565b80611cc65750505050610bd9565b60005b603454811015611e5557600060348281548110611ce257fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611d3557600080fd5b505afa158015611d49573d6000803e3d6000fd5b505050506040513d6020811015611d5f57600080fd5b5051905080611d6f575050611e4d565b6000611d81828663ffffffff61326b16565b6001600160a01b03808516600090815260406020819052902054919250168015801590611dae5750600082115b15611e485780611dce6001600160a01b038616828563ffffffff61328016565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611e2e57600080fd5b505af1158015611e42573d6000803e3d6000fd5b50505050505b505050505b600101611cc9565b5060005b60365481101561212757600060368281548110611e7257fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b158015611ebf57600080fd5b505afa158015611ed3573d6000803e3d6000fd5b505050506040513d6020811015611ee957600080fd5b505190506001600160a01b0381161561211d576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b5051905080611ff057306001600160a01b0316630e5c011e60368681548110611f8657fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b5050505061211b565b60008290506000816001600160a01b03166370a082316036888154811061201357fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561206157600080fd5b505afa158015612075573d6000803e3d6000fd5b505050506040513d602081101561208b57600080fd5b5051905082811061211857306001600160a01b0316630e5c011e603688815481106120b257fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b1580156120ff57600080fd5b505af1158015612113573d6000803e3d6000fd5b505050505b50505b505b5050600101611e59565b50604260009054906101000a90046001600160a01b03166001600160a01b0316638119c0656040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561217857600080fd5b505af115801561218c573d6000803e3d6000fd5b5050505050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116612216576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661222861171d565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3612266816132d2565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156122b457600080fd5b505afa1580156122c8573d6000803e3d6000fd5b505050506040513d60208110156122de57600080fd5b5051915060005b603654811015612423576000603682815481106122fe57fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561235457600080fd5b505afa158015612368573d6000803e3d6000fd5b505050506040513d602081101561237e57600080fd5b50511561241a57612417816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156123de57600080fd5b505afa1580156123f2573d6000803e3d6000fd5b505050506040513d602081101561240857600080fd5b5051859063ffffffff612df716565b93505b506001016122e5565b5050919050565b60606000612436610ed8565b905060606124446001612ce1565b9050606082604051908082528060200260200182016040528015612472578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156124a1578160200160208202803883390190505b5060408051868152602080880282010190915290915060009081908680156124d3578160200160208202803883390190505b50603854909750156125125760006124fc6127106119b06038548c612e9490919063ffffffff16565b905061250e898263ffffffff612f2f16565b9850505b60005b6034548110156125c257600061254b6034838154811061253157fe5b6000918252602090912001546001600160a01b0316612269565b9050600061255f603484815481106113cf57fe5b90508187848151811061256e57fe5b6020026020010181815250508086848151811061258757fe5b60209081029190910101526125b66125a983601284900363ffffffff6117fc16565b869063ffffffff612df716565b94505050600101612515565b5060005b6034548110156126735760008682815181106125de57fe5b60200260200101519050670de0b6b3a76400008110156126035750670de0b6b3a76400005b6000612655856119b0846126498a888151811061261c57fe5b60200260200101516012038c898151811061263357fe5b60200260200101516117fc90919063ffffffff16565b9063ffffffff612e9416565b9050612667848263ffffffff612df716565b935050506001016125c6565b506000612686898363ffffffff6132f616565b905060005b6034548110156126de576126bf846119b0848985815181106126a957fe5b6020026020010151612e9490919063ffffffff16565b8982815181106126cb57fe5b602090810291909101015260010161268b565b5050505050505050919050565b60008211612740576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561278557600080fd5b505afa158015612799573d6000803e3d6000fd5b505050506040513d60208110156127af57600080fd5b5051905060006127bd612cc0565b604154909150156128785760006127da838363ffffffff6132f616565b9050604154670de0b6b3a7640000821161280b57612806670de0b6b3a76400008363ffffffff612f2f16565b612823565b61282382670de0b6b3a764000063ffffffff612f2f16565b1115612876576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810186905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160606128be8561242a565b905060005b603454811015612b54578181815181106128d957fe5b6020026020010151600014156128ee57612b4c565b6000603482815481106128fd57fe5b60009182526020909120015483516001600160a01b03909116915083908390811061292457fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b5051106129e9576129e4338484815181106129c357fe5b6020026020010151836001600160a01b03166132809092919063ffffffff16565b612b4a565b600060406000603485815481106129fc57fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612b09576000819050806001600160a01b031663d9caed123360348781548110612a5157fe5b9060005260206000200160009054906101000a90046001600160a01b0316888881518110612a7b57fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612aeb57600080fd5b505af1158015612aff573d6000803e3d6000fd5b5050505050612b48565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b6001016128c3565b508315612c02576000805b8251811015612baa576000612b7a603483815481106113cf57fe5b9050612b9f612b928260120386858151811061263357fe5b849063ffffffff612df716565b925050600101612b5f565b5084811015612c00576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612c5557600080fd5b505af1158015612c69573d6000803e3d6000fd5b50505050603b5485118015612c885750603754600160a01b900460ff16155b15612c9557612c95611884565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612ccd613219565b612cd5613129565b9063ffffffff612df716565b6060612ceb610ed8565b604051908082528060200260200182016040528015612d14578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561242357612dd8600a836001600160a01b031663aea9107860348581548110612d5257fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015612da057600080fd5b505afa158015612db4573d6000803e3d6000fd5b505050506040513d6020811015612dca57600080fd5b50519063ffffffff6117fc16565b838281518110612de457fe5b6020908102919091010152600101612d27565b600082820183811015612e51576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612e8c57508115155b949350505050565b600082612ea357506000610be6565b82820282848281612eb057fe5b0414612e515760405162461bcd60e51b81526004018080602001828103825260218152602001806136106021913960400191505060405180910390fd5b6000612e5183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613323565b6000612e5183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506133c5565b612f83826001600160a01b0316612e58565b612fd4576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106130125780518252601f199092019160209182019101612ff3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613074576040519150601f19603f3d011682016040523d82523d6000602084013e613079565b606091505b5091509150816130d0576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611c05578080602001905160208110156130ec57600080fd5b5051611c055760405162461bcd60e51b815260040180806020018281038252602a815260200180613653602a913960400191505060405180910390fd5b6000805b6034548110156132155760006034828154811061314657fe5b6000918252602082200154603480546001600160a01b03909216935061317091859081106113cf57fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156131bc57600080fd5b505afa1580156131d0573d6000803e3d6000fd5b505050506040513d60208110156131e657600080fd5b50519050801561320a576132076125a982601285900363ffffffff6117fc16565b94505b50505060010161312d565b5090565b6000805b603654811015613215576132616132546036838154811061323a57fe5b6000918252602090912001546001600160a01b031661341f565b839063ffffffff612df716565b915060010161321d565b6000612e518383670de0b6b3a7640000611856565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611ba6908490612f71565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061331184670de0b6b3a764000063ffffffff612e9416565b9050612e8c818463ffffffff612eed16565b600081836133af5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561337457818101518382015260200161335c565b50505050905090810190601f1680156133a15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816133bb57fe5b0495945050505050565b600081848411156134175760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561337457818101518382015260200161335c565b505050900390565b600081815b603454811015612423576000613440603483815481106113cf57fe5b9050826001600160a01b031663aa388af66034848154811061345e57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156134ac57600080fd5b505afa1580156134c0573d6000803e3d6000fd5b505050506040513d60208110156134d657600080fd5b505115613599576000836001600160a01b0316635f515226603485815481106134fb57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561354957600080fd5b505afa15801561355d573d6000803e3d6000fd5b505050506040513d602081101561357357600080fd5b505190508015613597576135946125a982601285900363ffffffff6117fc16565b94505b505b5060010161342456fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820f5ce484058ce120d7bb6fefde3051498b9396da8f85e58bb4fb70cd2ed9251b264736f6c634300050b0032", "devdoc": { "methods": { "allocate()": { diff --git a/contracts/deployments/mainnet/solcInputs/cca309778b0bcb384ba7e2e97bde53a0.json b/contracts/deployments/mainnet/solcInputs/cca309778b0bcb384ba7e2e97bde53a0.json new file mode 100644 index 0000000000..c999e276fa --- /dev/null +++ b/contracts/deployments/mainnet/solcInputs/cca309778b0bcb384ba7e2e97bde53a0.json @@ -0,0 +1,317 @@ +{ + "language": "Solidity", + "sources": { + "contracts/buyback/Buyback.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { Governable } from \"../governance/Governable.sol\";\n\nimport { IUniswapV2Router } from \"../interfaces/uniswap/IUniswapV2Router02.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract Buyback is Governable {\n using SafeERC20 for IERC20;\n\n event UniswapUpdated(address _address);\n\n // Address of Uniswap\n address public uniswapAddr = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;\n\n // Address of OUSD Vault\n address constant public vaultAddr = 0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70;\n\n // Swap from OUSD\n IERC20 constant ousd = IERC20(0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86);\n\n // Swap to OGN\n IERC20 constant ogn = IERC20(0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26);\n\n // USDT for Uniswap path\n IERC20 constant usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n /**\n * @dev Verifies that the caller is the OUSD Vault.\n */\n modifier onlyVault() {\n require(vaultAddr == msg.sender, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @dev Set address of Uniswap for performing liquidation of strategy reward\n * tokens. Setting to 0x0 will pause swaps.\n * @param _address Address of Uniswap\n */\n function setUniswapAddr(address _address) external onlyGovernor {\n uniswapAddr = _address;\n // Give Uniswap unlimited OUSD allowance\n ousd.safeApprove(uniswapAddr, 0);\n ousd.safeApprove(uniswapAddr, uint256(-1));\n emit UniswapUpdated(_address);\n }\n\n /**\n * @dev Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible\n * protocol (e.g. Sushiswap)\n **/\n function swap() external onlyVault {\n if (uniswapAddr == address(0)) return;\n\n uint256 sourceAmount = ousd.balanceOf(address(this));\n if (sourceAmount < 1000 * 1e18) return;\n\n // Uniswap redemption path\n address[] memory path = new address[](4);\n path[0] = address(ousd);\n path[1] = address(usdt);\n path[2] = IUniswapV2Router(uniswapAddr).WETH();\n path[3] = address(ogn);\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\n sourceAmount,\n uint256(0),\n path,\n address(this),\n now\n );\n }\n\n /**\n * @notice Owner function to withdraw a specific amount of a token\n */\n function transferToken(address token, uint256 amount)\n external\n onlyGovernor\n nonReentrant\n {\n IERC20(token).safeTransfer(_governor(), amount);\n }\n}\n" + }, + "contracts/governance/Governable.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Governable Contract\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\n * from owner to governor and renounce methods removed. Does not use\n * Context.sol like Ownable.sol does for simplification.\n * @author Origin Protocol Inc\n */\ncontract Governable {\n // Storage position of the owner and pendingOwner of the contract\n // keccak256(\"OUSD.governor\");\n bytes32\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\n\n // keccak256(\"OUSD.pending.governor\");\n bytes32\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\n\n // keccak256(\"OUSD.reentry.status\");\n bytes32\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\n\n // See OpenZeppelin ReentrancyGuard implementation\n uint256 constant _NOT_ENTERED = 1;\n uint256 constant _ENTERED = 2;\n\n event PendingGovernorshipTransfer(\n address indexed previousGovernor,\n address indexed newGovernor\n );\n\n event GovernorshipTransferred(\n address indexed previousGovernor,\n address indexed newGovernor\n );\n\n /**\n * @dev Initializes the contract setting the deployer as the initial Governor.\n */\n constructor() internal {\n _setGovernor(msg.sender);\n emit GovernorshipTransferred(address(0), _governor());\n }\n\n /**\n * @dev Returns the address of the current Governor.\n */\n function governor() public view returns (address) {\n return _governor();\n }\n\n /**\n * @dev Returns the address of the current Governor.\n */\n function _governor() internal view returns (address governorOut) {\n bytes32 position = governorPosition;\n assembly {\n governorOut := sload(position)\n }\n }\n\n /**\n * @dev Returns the address of the pending Governor.\n */\n function _pendingGovernor()\n internal\n view\n returns (address pendingGovernor)\n {\n bytes32 position = pendingGovernorPosition;\n assembly {\n pendingGovernor := sload(position)\n }\n }\n\n /**\n * @dev Throws if called by any account other than the Governor.\n */\n modifier onlyGovernor() {\n require(isGovernor(), \"Caller is not the Governor\");\n _;\n }\n\n /**\n * @dev Returns true if the caller is the current Governor.\n */\n function isGovernor() public view returns (bool) {\n return msg.sender == _governor();\n }\n\n function _setGovernor(address newGovernor) internal {\n bytes32 position = governorPosition;\n assembly {\n sstore(position, newGovernor)\n }\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n bytes32 position = reentryStatusPosition;\n uint256 _reentry_status;\n assembly {\n _reentry_status := sload(position)\n }\n\n // On the first call to nonReentrant, _notEntered will be true\n require(_reentry_status != _ENTERED, \"Reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n assembly {\n sstore(position, _ENTERED)\n }\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n assembly {\n sstore(position, _NOT_ENTERED)\n }\n }\n\n function _setPendingGovernor(address newGovernor) internal {\n bytes32 position = pendingGovernorPosition;\n assembly {\n sstore(position, newGovernor)\n }\n }\n\n /**\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\n * Can only be called by the current Governor. Must be claimed for this to complete\n * @param _newGovernor Address of the new Governor\n */\n function transferGovernance(address _newGovernor) external onlyGovernor {\n _setPendingGovernor(_newGovernor);\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\n }\n\n /**\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\n * Can only be called by the new Governor.\n */\n function claimGovernance() external {\n require(\n msg.sender == _pendingGovernor(),\n \"Only the pending Governor can complete the claim\"\n );\n _changeGovernor(msg.sender);\n }\n\n /**\n * @dev Change Governance of the contract to a new account (`newGovernor`).\n * @param _newGovernor Address of the new Governor\n */\n function _changeGovernor(address _newGovernor) internal {\n require(_newGovernor != address(0), \"New Governor is address(0)\");\n emit GovernorshipTransferred(_governor(), _newGovernor);\n _setGovernor(_newGovernor);\n }\n}\n" + }, + "contracts/interfaces/uniswap/IUniswapV2Router02.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IUniswapV2Router {\n function WETH() external pure returns (address);\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n );\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\n * the optional functions; to access them see {ERC20Detailed}.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.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 ERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function callOptionalReturn(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.\n\n // A Solidity high level call has three parts:\n // 1. The target address is checked to verify it contains contract code\n // 2. The call itself is made, and success asserted\n // 3. The return value is decoded, which in turn checks the size of the returned data.\n // solhint-disable-next-line max-line-length\n require(address(token).isContract(), \"SafeERC20: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = address(token).call(data);\n require(success, \"SafeERC20: low-level call failed\");\n\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction overflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot overflow.\n *\n * _Available since v2.4.0._\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n *\n * _Available since v2.4.0._\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n *\n * _Available since v2.4.0._\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "pragma solidity ^0.5.5;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following \n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\n // for accounts without code, i.e. `keccak256('')`\n bytes32 codehash;\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n // solhint-disable-next-line no-inline-assembly\n assembly { codehash := extcodehash(account) }\n return (codehash != accountHash && codehash != 0x0);\n }\n\n /**\n * @dev Converts an `address` into `address payable`. Note that this is\n * simply a type cast: the actual underlying value is not changed.\n *\n * _Available since v2.4.0._\n */\n function toPayable(address account) internal pure returns (address payable) {\n return address(uint160(account));\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 * _Available since v2.4.0._\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-call-value\n (bool success, ) = recipient.call.value(amount)(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n}\n" + }, + "contracts/utils/InitializableAbstractStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport { Governable } from \"../governance/Governable.sol\";\n\ncontract InitializableAbstractStrategy is Initializable, Governable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n event PTokenAdded(address indexed _asset, address _pToken);\n event PTokenRemoved(address indexed _asset, address _pToken);\n event Deposit(address indexed _asset, address _pToken, uint256 _amount);\n event Withdrawal(address indexed _asset, address _pToken, uint256 _amount);\n event RewardTokenCollected(address recipient, uint256 amount);\n\n // Core address for the given platform\n address public platformAddress;\n\n address public vaultAddress;\n\n // asset => pToken (Platform Specific Token Address)\n mapping(address => address) public assetToPToken;\n\n // Full list of all assets supported here\n address[] internal assetsMapped;\n\n // Reward token address\n address public rewardTokenAddress;\n uint256 public rewardLiquidationThreshold;\n\n /**\n * @dev Internal initialize function, to set up initial internal state\n * @param _platformAddress jGeneric platform address\n * @param _vaultAddress Address of the Vault\n * @param _rewardTokenAddress Address of reward token for platform\n * @param _assets Addresses of initial supported assets\n * @param _pTokens Platform Token corresponding addresses\n */\n function initialize(\n address _platformAddress,\n address _vaultAddress,\n address _rewardTokenAddress,\n address[] calldata _assets,\n address[] calldata _pTokens\n ) external onlyGovernor initializer {\n InitializableAbstractStrategy._initialize(\n _platformAddress,\n _vaultAddress,\n _rewardTokenAddress,\n _assets,\n _pTokens\n );\n }\n\n function _initialize(\n address _platformAddress,\n address _vaultAddress,\n address _rewardTokenAddress,\n address[] memory _assets,\n address[] memory _pTokens\n ) internal {\n platformAddress = _platformAddress;\n vaultAddress = _vaultAddress;\n rewardTokenAddress = _rewardTokenAddress;\n uint256 assetCount = _assets.length;\n require(assetCount == _pTokens.length, \"Invalid input arrays\");\n for (uint256 i = 0; i < assetCount; i++) {\n _setPTokenAddress(_assets[i], _pTokens[i]);\n }\n }\n\n /**\n * @dev Collect accumulated reward token and send to Vault.\n */\n function collectRewardToken() external onlyVault nonReentrant {\n IERC20 rewardToken = IERC20(rewardTokenAddress);\n uint256 balance = rewardToken.balanceOf(address(this));\n emit RewardTokenCollected(vaultAddress, balance);\n rewardToken.safeTransfer(vaultAddress, balance);\n }\n\n /**\n * @dev Verifies that the caller is the Vault.\n */\n modifier onlyVault() {\n require(msg.sender == vaultAddress, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @dev Verifies that the caller is the Vault or Governor.\n */\n modifier onlyVaultOrGovernor() {\n require(\n msg.sender == vaultAddress || msg.sender == governor(),\n \"Caller is not the Vault or Governor\"\n );\n _;\n }\n\n /**\n * @dev Set the reward token address.\n * @param _rewardTokenAddress Address of the reward token\n */\n function setRewardTokenAddress(address _rewardTokenAddress)\n external\n onlyGovernor\n {\n rewardTokenAddress = _rewardTokenAddress;\n }\n\n /**\n * @dev Set the reward token liquidation threshold.\n * @param _threshold Threshold amount in decimals of reward token that will\n * cause the Vault to claim and withdrawAll on allocate() calls.\n */\n function setRewardLiquidationThreshold(uint256 _threshold)\n external\n onlyGovernor\n {\n rewardLiquidationThreshold = _threshold;\n }\n\n /**\n * @dev Provide support for asset by passing its pToken address.\n * This method can only be called by the system Governor\n * @param _asset Address for the asset\n * @param _pToken Address for the corresponding platform token\n */\n function setPTokenAddress(address _asset, address _pToken)\n external\n onlyGovernor\n {\n _setPTokenAddress(_asset, _pToken);\n }\n\n /**\n * @dev Remove a supported asset by passing its index.\n * This method can only be called by the system Governor\n * @param _assetIndex Index of the asset to be removed\n */\n function removePToken(uint256 _assetIndex) external onlyGovernor {\n require(_assetIndex < assetsMapped.length, \"Invalid index\");\n address asset = assetsMapped[_assetIndex];\n address pToken = assetToPToken[asset];\n\n if (_assetIndex < assetsMapped.length - 1) {\n assetsMapped[_assetIndex] = assetsMapped[assetsMapped.length - 1];\n }\n assetsMapped.pop();\n assetToPToken[asset] = address(0);\n\n emit PTokenRemoved(asset, pToken);\n }\n\n /**\n * @dev Provide support for asset by passing its pToken address.\n * Add to internal mappings and execute the platform specific,\n * abstract method `_abstractSetPToken`\n * @param _asset Address for the asset\n * @param _pToken Address for the corresponding platform token\n */\n function _setPTokenAddress(address _asset, address _pToken) internal {\n require(assetToPToken[_asset] == address(0), \"pToken already set\");\n require(\n _asset != address(0) && _pToken != address(0),\n \"Invalid addresses\"\n );\n\n assetToPToken[_asset] = _pToken;\n assetsMapped.push(_asset);\n\n emit PTokenAdded(_asset, _pToken);\n\n _abstractSetPToken(_asset, _pToken);\n }\n\n /**\n * @dev Transfer token to governor. Intended for recovering tokens stuck in\n * strategy contracts, i.e. mistaken sends.\n * @param _asset Address for the asset\n * @param _amount Amount of the asset to transfer\n */\n function transferToken(address _asset, uint256 _amount)\n public\n onlyGovernor\n {\n IERC20(_asset).safeTransfer(governor(), _amount);\n }\n\n /***************************************\n Abstract\n ****************************************/\n\n function _abstractSetPToken(address _asset, address _pToken) internal;\n\n function safeApproveAllTokens() external;\n\n /**\n * @dev Deposit a amount of asset into the platform\n * @param _asset Address for the asset\n * @param _amount Units of asset to deposit\n */\n function deposit(address _asset, uint256 _amount) external;\n\n /**\n * @dev Deposit balance of all supported assets into the platform\n */\n function depositAll() external;\n\n /**\n * @dev Withdraw an amount of asset from the platform.\n * @param _recipient Address to which the asset should be sent\n * @param _asset Address of the asset\n * @param _amount Units of asset to withdraw\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external;\n\n /**\n * @dev Withdraw all assets from strategy sending assets to Vault.\n */\n function withdrawAll() external;\n\n /**\n * @dev Get the total asset value held in the platform.\n * This includes any interest that was generated since depositing.\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance);\n\n /**\n * @dev Check if an asset is supported.\n * @param _asset Address of the asset\n * @return bool Whether asset is supported\n */\n function supportsAsset(address _asset) external view returns (bool);\n}\n" + }, + "@openzeppelin/upgrades/contracts/Initializable.sol": { + "content": "pragma solidity >=0.4.24 <0.7.0;\n\n\n/**\n * @title Initializable\n *\n * @dev Helper contract to support initializer functions. To use it, replace\n * the constructor with a function that has the `initializer` modifier.\n * WARNING: Unlike constructors, initializer functions must be manually\n * invoked. This applies both to deploying an Initializable contract, as well\n * as extending an Initializable contract via inheritance.\n * WARNING: When used with inheritance, manual care must be taken to not invoke\n * a parent initializer twice, or ensure that all initializers are idempotent,\n * because this is not dealt with automatically as with constructors.\n */\ncontract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private initializing;\n\n /**\n * @dev Modifier to use in the initializer function of a contract.\n */\n modifier initializer() {\n require(initializing || isConstructor() || !initialized, \"Contract instance has already been initialized\");\n\n bool isTopLevelCall = !initializing;\n if (isTopLevelCall) {\n initializing = true;\n initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function isConstructor() private view returns (bool) {\n // extcodesize checks the size of the code stored in an address, and\n // address returns the current address. Since the code is still not\n // deployed when running a constructor, any checks on its code size will\n // yield zero, making it an effective way to detect if a contract is\n // under construction or not.\n address self = address(this);\n uint256 cs;\n assembly { cs := extcodesize(self) }\n return cs == 0;\n }\n\n // Reserved storage space to allow for layout changes in the future.\n uint256[50] private ______gap;\n}\n" + }, + "contracts/strategies/ThreePoolStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title Curve 3Pool Strategy\n * @notice Investment strategy for investing stablecoins via Curve 3Pool\n * @author Origin Protocol Inc\n */\n\nimport { ICurvePool } from \"./ICurvePool.sol\";\nimport { ICurveGauge } from \"./ICurveGauge.sol\";\nimport { ICRVMinter } from \"./ICRVMinter.sol\";\nimport {\n IERC20,\n InitializableAbstractStrategy\n} from \"../utils/InitializableAbstractStrategy.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\nimport { Helpers } from \"../utils/Helpers.sol\";\n\ncontract ThreePoolStrategy is InitializableAbstractStrategy {\n using StableMath for uint256;\n\n event RewardTokenCollected(address recipient, uint256 amount);\n\n address crvGaugeAddress;\n address crvMinterAddress;\n uint256 constant maxSlippage = 1e16; // 1%, same as the Curve UI\n\n /**\n * Initializer for setting up strategy internal state. This overrides the\n * InitializableAbstractStrategy initializer as Curve strategies don't fit\n * well within that abstraction.\n * @param _platformAddress Address of the Curve 3pool\n * @param _vaultAddress Address of the vault\n * @param _rewardTokenAddress Address of CRV\n * @param _assets Addresses of supported assets. MUST be passed in the same\n * order as returned by coins on the pool contract, i.e.\n * DAI, USDC, USDT\n * @param _pTokens Platform Token corresponding addresses\n * @param _crvGaugeAddress Address of the Curve DAO gauge for this pool\n * @param _crvMinterAddress Address of the CRV minter for rewards\n */\n function initialize(\n address _platformAddress, // 3Pool address\n address _vaultAddress,\n address _rewardTokenAddress, // CRV\n address[] calldata _assets,\n address[] calldata _pTokens,\n address _crvGaugeAddress,\n address _crvMinterAddress\n ) external onlyGovernor initializer {\n // Should be set prior to abstract initialize call otherwise\n // abstractSetPToken calls will fail\n crvGaugeAddress = _crvGaugeAddress;\n crvMinterAddress = _crvMinterAddress;\n InitializableAbstractStrategy._initialize(\n _platformAddress,\n _vaultAddress,\n _rewardTokenAddress,\n _assets,\n _pTokens\n );\n }\n\n /**\n * @dev Collect accumulated CRV and send to Vault.\n */\n function collectRewardToken() external onlyVault nonReentrant {\n IERC20 crvToken = IERC20(rewardTokenAddress);\n ICRVMinter minter = ICRVMinter(crvMinterAddress);\n uint256 balance = crvToken.balanceOf(address(this));\n emit RewardTokenCollected(vaultAddress, balance);\n minter.mint(crvGaugeAddress);\n crvToken.safeTransfer(vaultAddress, balance);\n }\n\n /**\n * @dev Deposit asset into the Curve 3Pool\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n */\n function deposit(address _asset, uint256 _amount)\n external\n onlyVault\n nonReentrant\n {\n require(_amount > 0, \"Must deposit something\");\n emit Deposit(_asset, address(platformAddress), _amount);\n // 3Pool requires passing deposit amounts for all 3 assets, set to 0 for\n // all\n uint256[3] memory _amounts;\n uint256 poolCoinIndex = _getPoolCoinIndex(_asset);\n // Set the amount on the asset we want to deposit\n _amounts[poolCoinIndex] = _amount;\n ICurvePool curvePool = ICurvePool(platformAddress);\n uint256 assetDecimals = Helpers.getDecimals(_asset);\n uint256 depositValue = _amount\n .scaleBy(int8(18 - assetDecimals))\n .divPrecisely(curvePool.get_virtual_price());\n uint256 minMintAmount = depositValue.mulTruncate(\n uint256(1e18).sub(maxSlippage)\n );\n // Do the deposit to 3pool\n curvePool.add_liquidity(_amounts, minMintAmount);\n // Deposit into Gauge\n IERC20 pToken = IERC20(assetToPToken[_asset]);\n ICurveGauge(crvGaugeAddress).deposit(\n pToken.balanceOf(address(this)),\n address(this)\n );\n }\n\n /**\n * @dev Deposit the entire balance of any supported asset into the Curve 3pool\n */\n function depositAll() external onlyVault nonReentrant {\n uint256[3] memory _amounts = [uint256(0), uint256(0), uint256(0)];\n uint256 depositValue = 0;\n ICurvePool curvePool = ICurvePool(platformAddress);\n\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n address assetAddress = assetsMapped[i];\n uint256 balance = IERC20(assetAddress).balanceOf(address(this));\n if (balance > 0) {\n uint256 poolCoinIndex = _getPoolCoinIndex(assetAddress);\n // Set the amount on the asset we want to deposit\n _amounts[poolCoinIndex] = balance;\n uint256 assetDecimals = Helpers.getDecimals(assetAddress);\n // Get value of deposit in Curve LP token to later determine\n // the minMintAmount argument for add_liquidity\n depositValue = depositValue.add(\n balance.scaleBy(int8(18 - assetDecimals)).divPrecisely(\n curvePool.get_virtual_price()\n )\n );\n emit Deposit(assetAddress, address(platformAddress), balance);\n }\n }\n\n uint256 minMintAmount = depositValue.mulTruncate(\n uint256(1e18).sub(maxSlippage)\n );\n // Do the deposit to 3pool\n curvePool.add_liquidity(_amounts, minMintAmount);\n // Deposit into Gauge, the PToken is the same (3Crv) for all mapped\n // assets, so just get the address from the first one\n IERC20 pToken = IERC20(assetToPToken[assetsMapped[0]]);\n ICurveGauge(crvGaugeAddress).deposit(\n pToken.balanceOf(address(this)),\n address(this)\n );\n }\n\n /**\n * @dev Withdraw asset from Curve 3Pool\n * @param _recipient Address to receive withdrawn asset\n * @param _asset Address of asset to withdraw\n * @param _amount Amount of asset to withdraw\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external onlyVault nonReentrant {\n require(_recipient != address(0), \"Invalid recipient\");\n require(_amount > 0, \"Invalid amount\");\n\n emit Withdrawal(_asset, address(assetToPToken[_asset]), _amount);\n\n // Calculate how much of the pool token we need to withdraw\n (uint256 contractPTokens, , uint256 totalPTokens) = _getTotalPTokens();\n\n require(totalPTokens > 0, \"Insufficient 3CRV balance\");\n\n uint256 poolCoinIndex = _getPoolCoinIndex(_asset);\n // Calculate the max amount of the asset we'd get if we withdrew all the\n // platform tokens\n ICurvePool curvePool = ICurvePool(platformAddress);\n uint256 maxAmount = curvePool.calc_withdraw_one_coin(\n totalPTokens,\n int128(poolCoinIndex)\n );\n\n // Calculate how many platform tokens we need to withdraw the asset amount\n uint256 withdrawPTokens = totalPTokens.mul(_amount).div(maxAmount);\n if (contractPTokens < withdrawPTokens) {\n // Not enough of pool token exists on this contract, some must be\n // staked in Gauge, unstake difference\n ICurveGauge(crvGaugeAddress).withdraw(\n withdrawPTokens.sub(contractPTokens)\n );\n }\n\n // Calculate a minimum withdrawal amount\n uint256 assetDecimals = Helpers.getDecimals(_asset);\n // 3crv is 1e18, subtract slippage percentage and scale to asset\n // decimals\n uint256 minWithdrawAmount = withdrawPTokens\n .mulTruncate(uint256(1e18).sub(maxSlippage))\n .scaleBy(int8(assetDecimals - 18));\n\n curvePool.remove_liquidity_one_coin(\n withdrawPTokens,\n int128(poolCoinIndex),\n minWithdrawAmount\n );\n IERC20(_asset).safeTransfer(_recipient, _amount);\n\n // Transfer any leftover dust back to the vault buffer.\n uint256 dust = IERC20(_asset).balanceOf(address(this));\n if (dust > 0) {\n IERC20(_asset).safeTransfer(vaultAddress, dust);\n }\n }\n\n /**\n * @dev Remove all assets from platform and send them to Vault contract.\n */\n function withdrawAll() external onlyVaultOrGovernor nonReentrant {\n // Withdraw all from Gauge\n (, uint256 gaugePTokens, uint256 totalPTokens) = _getTotalPTokens();\n ICurveGauge(crvGaugeAddress).withdraw(gaugePTokens);\n uint256[3] memory minWithdrawAmounts = [\n uint256(0),\n uint256(0),\n uint256(0)\n ];\n // Calculate min withdrawal amounts for each coin\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n address assetAddress = assetsMapped[i];\n uint256 virtualBalance = checkBalance(assetAddress);\n uint256 poolCoinIndex = _getPoolCoinIndex(assetAddress);\n minWithdrawAmounts[poolCoinIndex] = virtualBalance.mulTruncate(\n uint256(1e18).sub(maxSlippage)\n );\n }\n // Remove liqudiity\n ICurvePool threePool = ICurvePool(platformAddress);\n threePool.remove_liquidity(totalPTokens, minWithdrawAmounts);\n // Transfer assets out ot Vault\n // Note that Curve will provide all 3 of the assets in 3pool even if\n // we have not set PToken addresses for all of them in this strategy\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n IERC20 asset = IERC20(threePool.coins(i));\n asset.safeTransfer(vaultAddress, asset.balanceOf(address(this)));\n }\n }\n\n /**\n * @dev Get the total asset value held in the platform\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n public\n view\n returns (uint256 balance)\n {\n require(assetToPToken[_asset] != address(0), \"Unsupported asset\");\n // LP tokens in this contract. This should generally be nothing as we\n // should always stake the full balance in the Gauge, but include for\n // safety\n (, , uint256 totalPTokens) = _getTotalPTokens();\n ICurvePool curvePool = ICurvePool(platformAddress);\n\n uint256 pTokenTotalSupply = IERC20(assetToPToken[_asset]).totalSupply();\n if (pTokenTotalSupply > 0) {\n uint256 curveBalance = IERC20(_asset).balanceOf(address(curvePool));\n if (curveBalance > 0) {\n balance = totalPTokens.mul(curveBalance).div(pTokenTotalSupply);\n }\n }\n }\n\n /**\n * @dev Retuns bool indicating whether asset is supported by strategy\n * @param _asset Address of the asset\n */\n function supportsAsset(address _asset) external view returns (bool) {\n return assetToPToken[_asset] != address(0);\n }\n\n /**\n * @dev Approve the spending of all assets by their corresponding pool tokens,\n * if for some reason is it necessary.\n */\n function safeApproveAllTokens() external {\n // This strategy is a special case since it only supports one asset\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n _abstractSetPToken(assetsMapped[i], assetToPToken[assetsMapped[i]]);\n }\n }\n\n /**\n * @dev Calculate the total platform token balance (i.e. 3CRV) that exist in\n * this contract or is staked in the Gauge (or in other words, the total\n * amount platform tokens we own).\n * @return totalPTokens Total amount of platform tokens in native decimals\n */\n function _getTotalPTokens()\n internal\n view\n returns (\n uint256 contractPTokens,\n uint256 gaugePTokens,\n uint256 totalPTokens\n )\n {\n contractPTokens = IERC20(assetToPToken[assetsMapped[0]]).balanceOf(\n address(this)\n );\n ICurveGauge gauge = ICurveGauge(crvGaugeAddress);\n gaugePTokens = gauge.balanceOf(address(this));\n totalPTokens = contractPTokens.add(gaugePTokens);\n }\n\n /**\n * @dev Call the necessary approvals for the Curve pool and gauge\n * @param _asset Address of the asset\n * @param _pToken Address of the corresponding platform token (i.e. 3CRV)\n */\n function _abstractSetPToken(address _asset, address _pToken) internal {\n IERC20 asset = IERC20(_asset);\n IERC20 pToken = IERC20(_pToken);\n // 3Pool for asset (required for adding liquidity)\n asset.safeApprove(platformAddress, 0);\n asset.safeApprove(platformAddress, uint256(-1));\n // 3Pool for LP token (required for removing liquidity)\n pToken.safeApprove(platformAddress, 0);\n pToken.safeApprove(platformAddress, uint256(-1));\n // Gauge for LP token\n pToken.safeApprove(crvGaugeAddress, 0);\n pToken.safeApprove(crvGaugeAddress, uint256(-1));\n }\n\n /**\n * @dev Get the index of the coin in 3pool\n */\n function _getPoolCoinIndex(address _asset) internal view returns (uint256) {\n for (uint256 i = 0; i < 3; i++) {\n if (assetsMapped[i] == _asset) return i;\n }\n revert(\"Invalid 3pool asset\");\n }\n}\n" + }, + "contracts/strategies/ICurvePool.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface ICurvePool {\n function get_virtual_price() external view returns (uint256);\n\n function add_liquidity(uint256[3] calldata _amounts, uint256 _min) external;\n\n function calc_token_amount(uint256[3] calldata _amounts, bool _deposit)\n external\n returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 _amount,\n int128 _index,\n uint256 _minAmount\n ) external;\n\n function remove_liquidity(\n uint256 _amount,\n uint256[3] calldata _minWithdrawAmounts\n ) external;\n\n function calc_withdraw_one_coin(uint256 _amount, int128 _index)\n external\n view\n returns (uint256);\n\n function coins(uint256 _index) external view returns (address);\n}\n" + }, + "contracts/strategies/ICurveGauge.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface ICurveGauge {\n function balanceOf(address account) external view returns (uint256);\n\n function deposit(uint256 value, address account) external;\n\n function withdraw(uint256 value) external;\n}\n" + }, + "contracts/strategies/ICRVMinter.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface ICRVMinter {\n function mint(address gaugeAddress) external;\n}\n" + }, + "contracts/utils/StableMath.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n// Based on StableMath from Stability Labs Pty. Ltd.\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\n\nlibrary StableMath {\n using SafeMath for uint256;\n\n /**\n * @dev Scaling unit for use in specific calculations,\n * where 1 * 10**18, or 1e18 represents a unit '1'\n */\n uint256 private constant FULL_SCALE = 1e18;\n\n /***************************************\n Helpers\n ****************************************/\n\n /**\n * @dev Adjust the scale of an integer\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\n */\n function scaleBy(uint256 x, int8 adjustment)\n internal\n pure\n returns (uint256)\n {\n if (adjustment > 0) {\n x = x.mul(10**uint256(adjustment));\n } else if (adjustment < 0) {\n x = x.div(10**uint256(adjustment * -1));\n }\n return x;\n }\n\n /***************************************\n Precise Arithmetic\n ****************************************/\n\n /**\n * @dev Multiplies two precise units, and then truncates by the full scale\n * @param x Left hand input to multiplication\n * @param y Right hand input to multiplication\n * @return Result after multiplying the two inputs and then dividing by the shared\n * scale unit\n */\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulTruncateScale(x, y, FULL_SCALE);\n }\n\n /**\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\n * @param x Left hand input to multiplication\n * @param y Right hand input to multiplication\n * @param scale Scale unit\n * @return Result after multiplying the two inputs and then dividing by the shared\n * scale unit\n */\n function mulTruncateScale(\n uint256 x,\n uint256 y,\n uint256 scale\n ) internal pure returns (uint256) {\n // e.g. assume scale = fullScale\n // z = 10e18 * 9e17 = 9e36\n uint256 z = x.mul(y);\n // return 9e38 / 1e18 = 9e18\n return z.div(scale);\n }\n\n /**\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\n * @param x Left hand input to multiplication\n * @param y Right hand input to multiplication\n * @return Result after multiplying the two inputs and then dividing by the shared\n * scale unit, rounded up to the closest base unit.\n */\n function mulTruncateCeil(uint256 x, uint256 y)\n internal\n pure\n returns (uint256)\n {\n // e.g. 8e17 * 17268172638 = 138145381104e17\n uint256 scaled = x.mul(y);\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\n return ceil.div(FULL_SCALE);\n }\n\n /**\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\n * @param x Left hand input to division\n * @param y Right hand input to division\n * @return Result after multiplying the left operand by the scale, and\n * executing the division on the right hand input.\n */\n function divPrecisely(uint256 x, uint256 y)\n internal\n pure\n returns (uint256)\n {\n // e.g. 8e18 * 1e18 = 8e36\n uint256 z = x.mul(FULL_SCALE);\n // e.g. 8e36 / 10e18 = 8e17\n return z.div(y);\n }\n}\n" + }, + "contracts/utils/Helpers.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IBasicToken } from \"../interfaces/IBasicToken.sol\";\n\nlibrary Helpers {\n /**\n * @notice Fetch the `symbol()` from an ERC20 token\n * @dev Grabs the `symbol()` from a contract\n * @param _token Address of the ERC20 token\n * @return string Symbol of the ERC20 token\n */\n function getSymbol(address _token) internal view returns (string memory) {\n string memory symbol = IBasicToken(_token).symbol();\n return symbol;\n }\n\n /**\n * @notice Fetch the `decimals()` from an ERC20 token\n * @dev Grabs the `decimals()` from a contract and fails if\n * the decimal value does not live within a certain range\n * @param _token Address of the ERC20 token\n * @return uint256 Decimals of the ERC20 token\n */\n function getDecimals(address _token) internal view returns (uint256) {\n uint256 decimals = IBasicToken(_token).decimals();\n require(\n decimals >= 4 && decimals <= 18,\n \"Token must have sufficient decimal places\"\n );\n\n return decimals;\n }\n}\n" + }, + "contracts/interfaces/IBasicToken.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IBasicToken {\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/vault/VaultStorage.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD VaultStorage Contract\n * @notice The VaultStorage contract defines the storage for the Vault contracts\n * @author Origin Protocol Inc\n */\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport { IStrategy } from \"../interfaces/IStrategy.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\nimport { OUSD } from \"../token/OUSD.sol\";\nimport \"../utils/Helpers.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\n\ncontract VaultStorage is Initializable, Governable {\n using SafeMath for uint256;\n using StableMath for uint256;\n using SafeMath for int256;\n using SafeERC20 for IERC20;\n\n event AssetSupported(address _asset);\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\n event StrategyApproved(address _addr);\n event StrategyRemoved(address _addr);\n event Mint(address _addr, uint256 _value);\n event Redeem(address _addr, uint256 _value);\n event CapitalPaused();\n event CapitalUnpaused();\n event RebasePaused();\n event RebaseUnpaused();\n event VaultBufferUpdated(uint256 _vaultBuffer);\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\n event PriceProviderUpdated(address _priceProvider);\n event AllocateThresholdUpdated(uint256 _threshold);\n event RebaseThresholdUpdated(uint256 _threshold);\n event UniswapUpdated(address _address);\n event StrategistUpdated(address _address);\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\n event TrusteeFeeBpsChanged(uint256 _basis);\n event TrusteeAddressChanged(address _address);\n\n // Assets supported by the Vault, i.e. Stablecoins\n struct Asset {\n bool isSupported;\n }\n mapping(address => Asset) assets;\n address[] allAssets;\n\n // Strategies approved for use by the Vault\n struct Strategy {\n bool isSupported;\n uint256 _deprecated; // Deprecated storage slot\n }\n mapping(address => Strategy) strategies;\n address[] allStrategies;\n\n // Address of the Oracle price provider contract\n address public priceProvider;\n // Pausing bools\n bool public rebasePaused = false;\n bool public capitalPaused = true;\n // Redemption fee in basis points\n uint256 public redeemFeeBps;\n // Buffer of assets to keep in Vault to handle (most) withdrawals\n uint256 public vaultBuffer;\n // Mints over this amount automatically allocate funds. 18 decimals.\n uint256 public autoAllocateThreshold;\n // Mints over this amount automatically rebase. 18 decimals.\n uint256 public rebaseThreshold;\n\n OUSD oUSD;\n\n //keccak256(\"OUSD.vault.governor.admin.impl\");\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\n\n // Address of the contract responsible for post rebase syncs with AMMs\n address private _deprecated_rebaseHooksAddr = address(0);\n\n // Address of Uniswap\n address public uniswapAddr = address(0);\n\n // Address of the Strategist\n address public strategistAddr = address(0);\n\n // Mapping of asset address to the Strategy that they should automatically\n // be allocated to\n mapping(address => address) public assetDefaultStrategies;\n\n uint256 public maxSupplyDiff;\n\n // Trustee contract that can collect a percentage of yield\n address public trusteeAddress;\n\n // Amount of yield collected in basis points\n uint256 public trusteeFeeBps;\n\n /**\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\n * @param newImpl address of the implementation\n */\n function setAdminImpl(address newImpl) external onlyGovernor {\n require(\n Address.isContract(newImpl),\n \"new implementation is not a contract\"\n );\n bytes32 position = adminImplPosition;\n assembly {\n sstore(position, newImpl)\n }\n }\n}\n" + }, + "contracts/interfaces/IStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\n */\ninterface IStrategy {\n /**\n * @dev Deposit the given asset to platform\n * @param _asset asset address\n * @param _amount Amount to deposit\n */\n function deposit(address _asset, uint256 _amount) external;\n\n /**\n * @dev Deposit the entire balance of all supported assets in the Strategy\n * to the platform\n */\n function depositAll() external;\n\n /**\n * @dev Withdraw given asset from Lending platform\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external;\n\n /**\n * @dev Liquidate all assets in strategy and return them to Vault.\n */\n function withdrawAll() external;\n\n /**\n * @dev Returns the current balance of the given asset.\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance);\n\n /**\n * @dev Returns bool indicating whether strategy supports asset.\n */\n function supportsAsset(address _asset) external view returns (bool);\n\n /**\n * @dev Collect reward tokens from the Strategy.\n */\n function collectRewardToken() external;\n\n /**\n * @dev The address of the reward token for the Strategy.\n */\n function rewardTokenAddress() external pure returns (address);\n\n /**\n * @dev The threshold (denominated in the reward token) over which the\n * vault will auto harvest on allocate calls.\n */\n function rewardLiquidationThreshold() external pure returns (uint256);\n}\n" + }, + "contracts/token/OUSD.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Token Contract\n * @dev ERC20 compatible contract for OUSD\n * @dev Implements an elastic supply\n * @author Origin Protocol Inc\n */\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport {\n InitializableERC20Detailed\n} from \"../utils/InitializableERC20Detailed.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\n/**\n * NOTE that this is an ERC20 token but the invariant that the sum of\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\n * rebasing design. Any integrations with OUSD should be aware.\n */\n\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\n using SafeMath for uint256;\n using StableMath for uint256;\n\n event TotalSupplyUpdated(\n uint256 totalSupply,\n uint256 rebasingCredits,\n uint256 rebasingCreditsPerToken\n );\n\n enum RebaseOptions { NotSet, OptOut, OptIn }\n\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\n uint256 public _totalSupply;\n mapping(address => mapping(address => uint256)) private _allowances;\n address public vaultAddress = address(0);\n mapping(address => uint256) private _creditBalances;\n uint256 public rebasingCredits;\n uint256 public rebasingCreditsPerToken;\n // Frozen address/credits are non rebasing (value is held in contracts which\n // do not receive yield unless they explicitly opt in)\n uint256 public nonRebasingSupply;\n mapping(address => uint256) public nonRebasingCreditsPerToken;\n mapping(address => RebaseOptions) public rebaseState;\n\n function initialize(\n string calldata _nameArg,\n string calldata _symbolArg,\n address _vaultAddress\n ) external onlyGovernor initializer {\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\n rebasingCreditsPerToken = 1e18;\n vaultAddress = _vaultAddress;\n }\n\n /**\n * @dev Verifies that the caller is the Savings Manager contract\n */\n modifier onlyVault() {\n require(vaultAddress == msg.sender, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @return The total supply of OUSD.\n */\n function totalSupply() public view returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev Gets the balance of the specified address.\n * @param _account Address to query the balance of.\n * @return A uint256 representing the _amount of base units owned by the\n * specified address.\n */\n function balanceOf(address _account) public view returns (uint256) {\n if (_creditBalances[_account] == 0) return 0;\n return\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\n }\n\n /**\n * @dev Gets the credits balance of the specified address.\n * @param _account The address to query the balance of.\n * @return (uint256, uint256) Credit balance and credits per token of the\n * address\n */\n function creditsBalanceOf(address _account)\n public\n view\n returns (uint256, uint256)\n {\n return (_creditBalances[_account], _creditsPerToken(_account));\n }\n\n /**\n * @dev Transfer tokens to a specified address.\n * @param _to the address to transfer to.\n * @param _value the _amount to be transferred.\n * @return true on success.\n */\n function transfer(address _to, uint256 _value) public returns (bool) {\n require(_to != address(0), \"Transfer to zero address\");\n require(\n _value <= balanceOf(msg.sender),\n \"Transfer greater than balance\"\n );\n\n _executeTransfer(msg.sender, _to, _value);\n\n emit Transfer(msg.sender, _to, _value);\n\n return true;\n }\n\n /**\n * @dev Transfer tokens from one address to another.\n * @param _from The address you want to send tokens from.\n * @param _to The address you want to transfer to.\n * @param _value The _amount of tokens to be transferred.\n */\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) public returns (bool) {\n require(_to != address(0), \"Transfer to zero address\");\n require(_value <= balanceOf(_from), \"Transfer greater than balance\");\n\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\n _value\n );\n\n _executeTransfer(_from, _to, _value);\n\n emit Transfer(_from, _to, _value);\n\n return true;\n }\n\n /**\n * @dev Update the count of non rebasing credits in response to a transfer\n * @param _from The address you want to send tokens from.\n * @param _to The address you want to transfer to.\n * @param _value Amount of OUSD to transfer\n */\n function _executeTransfer(\n address _from,\n address _to,\n uint256 _value\n ) internal {\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\n\n // Credits deducted and credited might be different due to the\n // differing creditsPerToken used by each account\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\n\n _creditBalances[_from] = _creditBalances[_from].sub(\n creditsDeducted,\n \"Transfer amount exceeds balance\"\n );\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\n\n if (isNonRebasingTo && !isNonRebasingFrom) {\n // Transfer to non-rebasing account from rebasing account, credits\n // are removed from the non rebasing tally\n nonRebasingSupply = nonRebasingSupply.add(_value);\n // Update rebasingCredits by subtracting the deducted amount\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\n // Transfer to rebasing account from non-rebasing account\n // Decreasing non-rebasing credits by the amount that was sent\n nonRebasingSupply = nonRebasingSupply.sub(_value);\n // Update rebasingCredits by adding the credited amount\n rebasingCredits = rebasingCredits.add(creditsCredited);\n }\n }\n\n /**\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\n * @param _owner The address which owns the funds.\n * @param _spender The address which will spend the funds.\n * @return The number of tokens still available for the _spender.\n */\n function allowance(address _owner, address _spender)\n public\n view\n returns (uint256)\n {\n return _allowances[_owner][_spender];\n }\n\n /**\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\n * msg.sender. This method is included for ERC20 compatibility.\n * increaseAllowance and decreaseAllowance should be used instead.\n * Changing an allowance with this method brings the risk that someone may transfer both\n * the old and the new allowance - if they are both greater than zero - if a transfer\n * transaction is mined before the later approve() call is mined.\n *\n * @param _spender The address which will spend the funds.\n * @param _value The _amount of tokens to be spent.\n */\n function approve(address _spender, uint256 _value) public returns (bool) {\n _allowances[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n /**\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\n * This method should be used instead of approve() to avoid the double approval vulnerability\n * described above.\n * @param _spender The address which will spend the funds.\n * @param _addedValue The _amount of tokens to increase the allowance by.\n */\n function increaseAllowance(address _spender, uint256 _addedValue)\n public\n returns (bool)\n {\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\n .add(_addedValue);\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\n return true;\n }\n\n /**\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\n * @param _spender The address which will spend the funds.\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\n */\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\n public\n returns (bool)\n {\n uint256 oldValue = _allowances[msg.sender][_spender];\n if (_subtractedValue >= oldValue) {\n _allowances[msg.sender][_spender] = 0;\n } else {\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\n }\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\n return true;\n }\n\n /**\n * @dev Mints new tokens, increasing totalSupply.\n */\n function mint(address _account, uint256 _amount) external onlyVault {\n _mint(_account, _amount);\n }\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 * - `to` cannot be the zero address.\n */\n function _mint(address _account, uint256 _amount) internal nonReentrant {\n require(_account != address(0), \"Mint to the zero address\");\n\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\n\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\n\n // If the account is non rebasing and doesn't have a set creditsPerToken\n // then set it i.e. this is a mint from a fresh contract\n if (isNonRebasingAccount) {\n nonRebasingSupply = nonRebasingSupply.add(_amount);\n } else {\n rebasingCredits = rebasingCredits.add(creditAmount);\n }\n\n _totalSupply = _totalSupply.add(_amount);\n\n require(_totalSupply < MAX_SUPPLY, \"Max supply\");\n\n emit Transfer(address(0), _account, _amount);\n }\n\n /**\n * @dev Burns tokens, decreasing totalSupply.\n */\n function burn(address account, uint256 amount) external onlyVault {\n _burn(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 nonReentrant {\n require(_account != address(0), \"Burn from the zero address\");\n if (_amount == 0) {\n return;\n }\n\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\n uint256 currentCredits = _creditBalances[_account];\n\n // Remove the credits, burning rounding errors\n if (\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\n ) {\n // Handle dust from rounding\n _creditBalances[_account] = 0;\n } else if (currentCredits > creditAmount) {\n _creditBalances[_account] = _creditBalances[_account].sub(\n creditAmount\n );\n } else {\n revert(\"Remove exceeds balance\");\n }\n\n // Remove from the credit tallies and non-rebasing supply\n if (isNonRebasingAccount) {\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\n } else {\n rebasingCredits = rebasingCredits.sub(creditAmount);\n }\n\n _totalSupply = _totalSupply.sub(_amount);\n\n emit Transfer(_account, address(0), _amount);\n }\n\n /**\n * @dev Get the credits per token for an account. Returns a fixed amount\n * if the account is non-rebasing.\n * @param _account Address of the account.\n */\n function _creditsPerToken(address _account)\n internal\n view\n returns (uint256)\n {\n if (nonRebasingCreditsPerToken[_account] != 0) {\n return nonRebasingCreditsPerToken[_account];\n } else {\n return rebasingCreditsPerToken;\n }\n }\n\n /**\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\n * Also, ensure contracts are non-rebasing if they have not opted in.\n * @param _account Address of the account.\n */\n function _isNonRebasingAccount(address _account) internal returns (bool) {\n bool isContract = Address.isContract(_account);\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\n _ensureRebasingMigration(_account);\n }\n return nonRebasingCreditsPerToken[_account] > 0;\n }\n\n /**\n * @dev Ensures internal account for rebasing and non-rebasing credits and\n * supply is updated following deployment of frozen yield change.\n */\n function _ensureRebasingMigration(address _account) internal {\n if (nonRebasingCreditsPerToken[_account] == 0) {\n // Set fixed credits per token for this account\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\n // Update non rebasing supply\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\n // Update credit tallies\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\n }\n }\n\n /**\n * @dev Add a contract address to the non rebasing exception list. I.e. the\n * address's balance will be part of rebases so the account will be exposed\n * to upside and downside.\n */\n function rebaseOptIn() public nonReentrant {\n require(_isNonRebasingAccount(msg.sender), \"Account has not opted out\");\n\n // Convert balance into the same amount at the current exchange rate\n uint256 newCreditBalance = _creditBalances[msg.sender]\n .mul(rebasingCreditsPerToken)\n .div(_creditsPerToken(msg.sender));\n\n // Decreasing non rebasing supply\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\n\n _creditBalances[msg.sender] = newCreditBalance;\n\n // Increase rebasing credits, totalSupply remains unchanged so no\n // adjustment necessary\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\n\n rebaseState[msg.sender] = RebaseOptions.OptIn;\n\n // Delete any fixed credits per token\n delete nonRebasingCreditsPerToken[msg.sender];\n }\n\n /**\n * @dev Remove a contract address to the non rebasing exception list.\n */\n function rebaseOptOut() public nonReentrant {\n require(!_isNonRebasingAccount(msg.sender), \"Account has not opted in\");\n\n // Increase non rebasing supply\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\n // Set fixed credits per token\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\n\n // Decrease rebasing credits, total supply remains unchanged so no\n // adjustment necessary\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\n\n // Mark explicitly opted out of rebasing\n rebaseState[msg.sender] = RebaseOptions.OptOut;\n }\n\n /**\n * @dev Modify the supply without minting new tokens. This uses a change in\n * the exchange rate between \"credits\" and OUSD tokens to change balances.\n * @param _newTotalSupply New total supply of OUSD.\n * @return uint256 representing the new total supply.\n */\n function changeSupply(uint256 _newTotalSupply)\n external\n onlyVault\n nonReentrant\n {\n require(_totalSupply > 0, \"Cannot increase 0 supply\");\n\n if (_totalSupply == _newTotalSupply) {\n emit TotalSupplyUpdated(\n _totalSupply,\n rebasingCredits,\n rebasingCreditsPerToken\n );\n return;\n }\n\n _totalSupply = _newTotalSupply > MAX_SUPPLY\n ? MAX_SUPPLY\n : _newTotalSupply;\n\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\n _totalSupply.sub(nonRebasingSupply)\n );\n\n require(rebasingCreditsPerToken > 0, \"Invalid change in supply\");\n\n _totalSupply = rebasingCredits\n .divPrecisely(rebasingCreditsPerToken)\n .add(nonRebasingSupply);\n\n emit TotalSupplyUpdated(\n _totalSupply,\n rebasingCredits,\n rebasingCreditsPerToken\n );\n }\n}\n" + }, + "contracts/utils/InitializableERC20Detailed.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @dev Optional functions from the ERC20 standard.\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\n */\ncontract InitializableERC20Detailed is IERC20 {\n // Storage gap to skip storage from prior to OUSD reset\n uint256[100] private _____gap;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\n * these values are immutable: they can only be set once during\n * construction.\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\n */\n function _initialize(\n string memory nameArg,\n string memory symbolArg,\n uint8 decimalsArg\n ) internal {\n _name = nameArg;\n _symbol = symbolArg;\n _decimals = decimalsArg;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view 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 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.\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 returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/vault/VaultAdmin.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Vault Admin Contract\n * @notice The VaultAdmin contract makes configuration and admin calls on the vault.\n * @author Origin Protocol Inc\n */\n\nimport \"./VaultStorage.sol\";\nimport { IOracle } from \"../interfaces/IOracle.sol\";\nimport { IUniswapV2Router } from \"../interfaces/uniswap/IUniswapV2Router02.sol\";\n\ncontract VaultAdmin is VaultStorage {\n /**\n * @dev Verifies that the caller is the Vault, Governor, or Strategist.\n */\n modifier onlyVaultOrGovernorOrStrategist() {\n require(\n msg.sender == address(this) ||\n msg.sender == strategistAddr ||\n isGovernor(),\n \"Caller is not the Vault, Governor, or Strategist\"\n );\n _;\n }\n\n modifier onlyGovernorOrStrategist() {\n require(\n msg.sender == strategistAddr || isGovernor(),\n \"Caller is not the Strategist or Governor\"\n );\n _;\n }\n\n /***************************************\n Configuration\n ****************************************/\n\n /**\n * @dev Set address of price provider.\n * @param _priceProvider Address of price provider\n */\n function setPriceProvider(address _priceProvider) external onlyGovernor {\n priceProvider = _priceProvider;\n emit PriceProviderUpdated(_priceProvider);\n }\n\n /**\n * @dev Set a fee in basis points to be charged for a redeem.\n * @param _redeemFeeBps Basis point fee to be charged\n */\n function setRedeemFeeBps(uint256 _redeemFeeBps) external onlyGovernor {\n redeemFeeBps = _redeemFeeBps;\n emit RedeemFeeUpdated(_redeemFeeBps);\n }\n\n /**\n * @dev Set a buffer of assets to keep in the Vault to handle most\n * redemptions without needing to spend gas unwinding assets from a Strategy.\n * @param _vaultBuffer Percentage using 18 decimals. 100% = 1e18.\n */\n function setVaultBuffer(uint256 _vaultBuffer)\n external\n onlyGovernorOrStrategist\n {\n require(_vaultBuffer <= 1e18, \"Invalid value\");\n vaultBuffer = _vaultBuffer;\n emit VaultBufferUpdated(_vaultBuffer);\n }\n\n /**\n * @dev Sets the minimum amount of OUSD in a mint to trigger an\n * automatic allocation of funds afterwords.\n * @param _threshold OUSD amount with 18 fixed decimals.\n */\n function setAutoAllocateThreshold(uint256 _threshold)\n external\n onlyGovernor\n {\n autoAllocateThreshold = _threshold;\n emit AllocateThresholdUpdated(_threshold);\n }\n\n /**\n * @dev Set a minimum amount of OUSD in a mint or redeem that triggers a\n * rebase\n * @param _threshold OUSD amount with 18 fixed decimals.\n */\n function setRebaseThreshold(uint256 _threshold) external onlyGovernor {\n rebaseThreshold = _threshold;\n emit RebaseThresholdUpdated(_threshold);\n }\n\n /**\n * @dev Set address of Uniswap for performing liquidation of strategy reward\n * tokens\n * @param _address Address of Uniswap\n */\n function setUniswapAddr(address _address) external onlyGovernor {\n uniswapAddr = _address;\n emit UniswapUpdated(_address);\n }\n\n /**\n * @dev Set address of Strategist\n * @param _address Address of Strategist\n */\n function setStrategistAddr(address _address) external onlyGovernor {\n strategistAddr = _address;\n emit StrategistUpdated(_address);\n }\n\n /**\n * @dev Set the default Strategy for an asset, i.e. the one which the asset\n will be automatically allocated to and withdrawn from\n * @param _asset Address of the asset\n * @param _strategy Address of the Strategy\n */\n function setAssetDefaultStrategy(address _asset, address _strategy)\n external\n onlyGovernorOrStrategist\n {\n emit AssetDefaultStrategyUpdated(_asset, _strategy);\n require(strategies[_strategy].isSupported, \"Strategy not approved\");\n IStrategy strategy = IStrategy(_strategy);\n require(assets[_asset].isSupported, \"Asset is not supported\");\n require(\n strategy.supportsAsset(_asset),\n \"Asset not supported by Strategy\"\n );\n assetDefaultStrategies[_asset] = _strategy;\n }\n\n /**\n * @dev Add a supported asset to the contract, i.e. one that can be\n * to mint OUSD.\n * @param _asset Address of asset\n */\n function supportAsset(address _asset) external onlyGovernor {\n require(!assets[_asset].isSupported, \"Asset already supported\");\n\n assets[_asset] = Asset({ isSupported: true });\n allAssets.push(_asset);\n\n // Verify that our oracle supports the asset\n // slither-disable-next-line unused-return\n IOracle(priceProvider).price(_asset);\n\n emit AssetSupported(_asset);\n }\n\n /**\n * @dev Add a strategy to the Vault.\n * @param _addr Address of the strategy to add\n */\n function approveStrategy(address _addr) external onlyGovernor {\n require(!strategies[_addr].isSupported, \"Strategy already approved\");\n strategies[_addr] = Strategy({ isSupported: true, _deprecated: 0 });\n allStrategies.push(_addr);\n emit StrategyApproved(_addr);\n }\n\n /**\n * @dev Remove a strategy from the Vault. Removes all invested assets and\n * returns them to the Vault.\n * @param _addr Address of the strategy to remove\n */\n\n function removeStrategy(address _addr) external onlyGovernor {\n require(strategies[_addr].isSupported, \"Strategy not approved\");\n\n // Initialize strategyIndex with out of bounds result so function will\n // revert if no valid index found\n uint256 strategyIndex = allStrategies.length;\n for (uint256 i = 0; i < allStrategies.length; i++) {\n if (allStrategies[i] == _addr) {\n strategyIndex = i;\n break;\n }\n }\n\n if (strategyIndex < allStrategies.length) {\n allStrategies[strategyIndex] = allStrategies[allStrategies.length -\n 1];\n allStrategies.pop();\n\n // Withdraw all assets\n IStrategy strategy = IStrategy(_addr);\n strategy.withdrawAll();\n // Call harvest after withdraw in case withdraw triggers\n // distribution of additional reward tokens (true for Compound)\n _harvest(_addr);\n emit StrategyRemoved(_addr);\n }\n\n // Clean up struct in mapping, this can be removed later\n // See https://github.com/OriginProtocol/origin-dollar/issues/324\n strategies[_addr].isSupported = false;\n }\n\n /**\n * @notice Move assets from one Strategy to another\n * @param _strategyFromAddress Address of Strategy to move assets from.\n * @param _strategyToAddress Address of Strategy to move assets to.\n * @param _assets Array of asset address that will be moved\n * @param _amounts Array of amounts of each corresponding asset to move.\n */\n function reallocate(\n address _strategyFromAddress,\n address _strategyToAddress,\n address[] calldata _assets,\n uint256[] calldata _amounts\n ) external onlyGovernorOrStrategist {\n require(\n strategies[_strategyFromAddress].isSupported,\n \"Invalid from Strategy\"\n );\n require(\n strategies[_strategyToAddress].isSupported,\n \"Invalid to Strategy\"\n );\n require(_assets.length == _amounts.length, \"Parameter length mismatch\");\n\n IStrategy strategyFrom = IStrategy(_strategyFromAddress);\n IStrategy strategyTo = IStrategy(_strategyToAddress);\n\n for (uint256 i = 0; i < _assets.length; i++) {\n require(strategyTo.supportsAsset(_assets[i]), \"Asset unsupported\");\n // Withdraw from Strategy and pass other Strategy as recipient\n strategyFrom.withdraw(address(strategyTo), _assets[i], _amounts[i]);\n }\n // Tell new Strategy to deposit into protocol\n strategyTo.depositAll();\n }\n\n /**\n * @dev Sets the maximum allowable difference between\n * total supply and backing assets' value.\n */\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor {\n maxSupplyDiff = _maxSupplyDiff;\n emit MaxSupplyDiffChanged(_maxSupplyDiff);\n }\n\n /**\n * @dev Sets the trusteeAddress that can receive a portion of yield.\n * Setting to the zero address disables this feature.\n */\n function setTrusteeAddress(address _address) external onlyGovernor {\n trusteeAddress = _address;\n emit TrusteeAddressChanged(_address);\n }\n\n /**\n * @dev Sets the TrusteeFeeBps to the percentage of yield that should be\n * received in basis points.\n */\n function setTrusteeFeeBps(uint256 _basis) external onlyGovernor {\n require(_basis <= 5000, \"basis cannot exceed 50%\");\n trusteeFeeBps = _basis;\n emit TrusteeFeeBpsChanged(_basis);\n }\n\n /***************************************\n Pause\n ****************************************/\n\n /**\n * @dev Set the deposit paused flag to true to prevent rebasing.\n */\n function pauseRebase() external onlyGovernorOrStrategist {\n rebasePaused = true;\n emit RebasePaused();\n }\n\n /**\n * @dev Set the deposit paused flag to true to allow rebasing.\n */\n function unpauseRebase() external onlyGovernor {\n rebasePaused = false;\n emit RebaseUnpaused();\n }\n\n /**\n * @dev Set the deposit paused flag to true to prevent capital movement.\n */\n function pauseCapital() external onlyGovernorOrStrategist {\n capitalPaused = true;\n emit CapitalPaused();\n }\n\n /**\n * @dev Set the deposit paused flag to false to enable capital movement.\n */\n function unpauseCapital() external onlyGovernorOrStrategist {\n capitalPaused = false;\n emit CapitalUnpaused();\n }\n\n /***************************************\n Rewards\n ****************************************/\n\n /**\n * @dev Transfer token to governor. Intended for recovering tokens stuck in\n * contract, i.e. mistaken sends.\n * @param _asset Address for the asset\n * @param _amount Amount of the asset to transfer\n */\n function transferToken(address _asset, uint256 _amount)\n external\n onlyGovernor\n {\n require(!assets[_asset].isSupported, \"Only unsupported assets\");\n IERC20(_asset).safeTransfer(governor(), _amount);\n }\n\n /**\n * @dev Collect reward tokens from all strategies and swap for supported\n * stablecoin via Uniswap\n */\n function harvest() external onlyGovernorOrStrategist {\n for (uint256 i = 0; i < allStrategies.length; i++) {\n _harvest(allStrategies[i]);\n }\n }\n\n /**\n * @dev Collect reward tokens for a specific strategy and swap for supported\n * stablecoin via Uniswap. Called from the vault.\n * @param _strategyAddr Address of the strategy to collect rewards from\n */\n function harvest(address _strategyAddr)\n external\n onlyVaultOrGovernorOrStrategist\n returns (uint256[] memory)\n {\n return _harvest(_strategyAddr);\n }\n\n /**\n * @dev Collect reward tokens from a single strategy and swap them for a\n * supported stablecoin via Uniswap\n * @param _strategyAddr Address of the strategy to collect rewards from\n */\n function _harvest(address _strategyAddr)\n internal\n returns (uint256[] memory)\n {\n IStrategy strategy = IStrategy(_strategyAddr);\n address rewardTokenAddress = strategy.rewardTokenAddress();\n if (rewardTokenAddress != address(0)) {\n strategy.collectRewardToken();\n\n if (uniswapAddr != address(0)) {\n IERC20 rewardToken = IERC20(strategy.rewardTokenAddress());\n uint256 rewardTokenAmount = rewardToken.balanceOf(\n address(this)\n );\n if (rewardTokenAmount > 0) {\n // Give Uniswap full amount allowance\n rewardToken.safeApprove(uniswapAddr, 0);\n rewardToken.safeApprove(uniswapAddr, rewardTokenAmount);\n\n // Uniswap redemption path\n address[] memory path = new address[](3);\n path[0] = strategy.rewardTokenAddress();\n path[1] = IUniswapV2Router(uniswapAddr).WETH();\n path[2] = allAssets[1]; // USDT\n\n return\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\n rewardTokenAmount,\n uint256(0),\n path,\n address(this),\n now.add(1800)\n );\n }\n }\n }\n }\n\n /***************************************\n Pricing\n ****************************************/\n\n /**\n * @dev Returns the total price in 18 digit USD for a given asset.\n * Never goes above 1, since that is how we price mints\n * @param asset address of the asset\n * @return uint256 USD price of 1 of the asset, in 18 decimal fixed\n */\n function priceUSDMint(address asset) external view returns (uint256) {\n uint256 price = IOracle(priceProvider).price(asset);\n if (price > 1e8) {\n price = 1e8;\n }\n // Price from Oracle is returned with 8 decimals\n // scale to 18 so 18-8=10\n return price.scaleBy(10);\n }\n\n /**\n * @dev Returns the total price in 18 digit USD for a given asset.\n * Never goes below 1, since that is how we price redeems\n * @param asset Addresss of the asset\n * @return uint256 USD price of 1 of the asset, in 18 decimal fixed\n */\n function priceUSDRedeem(address asset) external view returns (uint256) {\n uint256 price = IOracle(priceProvider).price(asset);\n if (price < 1e8) {\n price = 1e8;\n }\n // Price from Oracle is returned with 8 decimals\n // scale to 18 so 18-8=10\n return price.scaleBy(10);\n }\n\n /***************************************\n Strategies Admin\n ****************************************/\n\n /**\n * @dev Withdraws all assets from the strategy and sends assets to the Vault.\n * @param _strategyAddr Strategy address.\n */\n function withdrawAllFromStrategy(address _strategyAddr)\n external\n onlyGovernorOrStrategist\n {\n require(\n strategies[_strategyAddr].isSupported,\n \"Strategy is not supported\"\n );\n IStrategy strategy = IStrategy(_strategyAddr);\n strategy.withdrawAll();\n }\n\n /**\n * @dev Withdraws all assets from all the strategies and sends assets to the Vault.\n */\n function withdrawAllFromStrategies() external onlyGovernorOrStrategist {\n for (uint256 i = 0; i < allStrategies.length; i++) {\n IStrategy strategy = IStrategy(allStrategies[i]);\n strategy.withdrawAll();\n }\n }\n}\n" + }, + "contracts/interfaces/IOracle.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IOracle {\n /**\n * @dev returns the asset price in USD, 8 decimal digits.\n */\n function price(address asset) external view returns (uint256);\n}\n" + }, + "contracts/mocks/MockUniswapRouter.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IUniswapV2Router } from \"../interfaces/uniswap/IUniswapV2Router02.sol\";\nimport { Helpers } from \"../utils/Helpers.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\n\ncontract MockUniswapRouter is IUniswapV2Router {\n using StableMath for uint256;\n\n address tok0;\n address tok1;\n\n address public WETH = address(0);\n\n function initialize(address _token0, address _token1) public {\n tok0 = _token0;\n tok1 = _token1;\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts) {\n IERC20(tok0).transferFrom(msg.sender, address(this), amountIn);\n IERC20(tok1).transfer(\n to,\n amountIn.scaleBy(\n int8(Helpers.getDecimals(tok1) - Helpers.getDecimals(tok0))\n )\n );\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // this is needed to make this contract whole else it'd be just virtual\n }\n}\n" + }, + "contracts/staking/SingleAssetStaking.sol": { + "content": "pragma solidity 0.5.11;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\n\ncontract SingleAssetStaking is Initializable, Governable {\n using SafeMath for uint256;\n using StableMath for uint256;\n using SafeERC20 for IERC20;\n\n /* ========== STATE VARIABLES ========== */\n\n IERC20 public stakingToken; // this is both the staking and rewards\n\n struct Stake {\n uint256 amount; // amount to stake\n uint256 end; // when does the staking period end\n uint256 duration; // the duration of the stake\n uint240 rate; // rate to charge use 248 to reserve 8 bits for the bool\n bool paid;\n uint8 stakeType;\n }\n\n struct DropRoot {\n bytes32 hash;\n uint256 depth;\n }\n\n uint256[] public durations; // allowed durations\n uint256[] public rates; // rates that correspond with the allowed durations\n\n uint256 public totalOutstanding;\n bool public paused;\n\n mapping(address => Stake[]) public userStakes;\n\n mapping(uint8 => DropRoot) public dropRoots;\n\n // type 0 is reserved for stakes done by the user, all other types will be drop/preApproved stakes\n uint8 constant USER_STAKE_TYPE = 0;\n uint256 constant MAX_STAKES = 256;\n\n /* ========== Initialize ========== */\n\n /**\n * @dev Initialize the contracts, sets up durations, rates, and preApprover\n * for preApproved contracts can only be called once\n * @param _stakingToken Address of the token that we are staking\n * @param _durations Array of allowed durations in seconds\n * @param _rates Array of rates(0.3 is 30%) that correspond to the allowed\n * durations in 1e18 precision\n */\n function initialize(\n address _stakingToken,\n uint256[] calldata _durations,\n uint256[] calldata _rates\n ) external onlyGovernor initializer {\n stakingToken = IERC20(_stakingToken);\n _setDurationRates(_durations, _rates);\n }\n\n /* ========= Internal helper functions ======== */\n\n /**\n * @dev Validate and set the duration and corresponding rates, will emit\n * events NewRate and NewDurations\n */\n function _setDurationRates(\n uint256[] memory _durations,\n uint256[] memory _rates\n ) internal {\n require(\n _rates.length == _durations.length,\n \"Mismatch durations and rates\"\n );\n\n for (uint256 i = 0; i < _rates.length; i++) {\n require(_rates[i] < uint240(-1), \"Max rate exceeded\");\n }\n\n rates = _rates;\n durations = _durations;\n\n emit NewRates(msg.sender, rates);\n emit NewDurations(msg.sender, durations);\n }\n\n function _totalExpectedRewards(Stake[] storage stakes)\n internal\n view\n returns (uint256 total)\n {\n for (uint256 i = 0; i < stakes.length; i++) {\n Stake storage stake = stakes[i];\n if (!stake.paid) {\n total = total.add(stake.amount.mulTruncate(stake.rate));\n }\n }\n }\n\n function _totalExpected(Stake storage _stake)\n internal\n view\n returns (uint256)\n {\n return _stake.amount.add(_stake.amount.mulTruncate(_stake.rate));\n }\n\n function _airDroppedStakeClaimed(address account, uint8 stakeType)\n internal\n view\n returns (bool)\n {\n Stake[] storage stakes = userStakes[account];\n for (uint256 i = 0; i < stakes.length; i++) {\n if (stakes[i].stakeType == stakeType) {\n return true;\n }\n }\n return false;\n }\n\n function _findDurationRate(uint256 duration)\n internal\n view\n returns (uint240)\n {\n for (uint256 i = 0; i < durations.length; i++) {\n if (duration == durations[i]) {\n return uint240(rates[i]);\n }\n }\n return 0;\n }\n\n /**\n * @dev Internal staking function\n * will insert the stake into the stakes array and verify we have\n * enough to pay off stake + reward\n * @param staker Address of the staker\n * @param stakeType Number that represent the type of the stake, 0 is user\n * initiated all else is currently preApproved\n * @param duration Number of seconds this stake will be held for\n * @param rate Rate(0.3 is 30%) of reward for this stake in 1e18, uint240 =\n * to fit the bool and type in struct Stake\n * @param amount Number of tokens to stake in 1e18\n */\n function _stake(\n address staker,\n uint8 stakeType,\n uint256 duration,\n uint240 rate,\n uint256 amount\n ) internal {\n require(!paused, \"Staking paused\");\n\n Stake[] storage stakes = userStakes[staker];\n\n uint256 end = block.timestamp.add(duration);\n\n uint256 i = stakes.length; // start at the end of the current array\n\n require(i < MAX_STAKES, \"Max stakes\");\n\n stakes.length += 1; // grow the array\n // find the spot where we can insert the current stake\n // this should make an increasing list sorted by end\n while (i != 0 && stakes[i - 1].end > end) {\n // shift it back one\n stakes[i] = stakes[i - 1];\n i -= 1;\n }\n\n // insert the stake\n Stake storage newStake = stakes[i];\n newStake.rate = rate;\n newStake.stakeType = stakeType;\n newStake.end = end;\n newStake.duration = duration;\n newStake.amount = amount;\n\n totalOutstanding = totalOutstanding.add(_totalExpected(newStake));\n\n emit Staked(staker, amount, duration, rate);\n }\n\n function _stakeWithChecks(\n address staker,\n uint256 amount,\n uint256 duration\n ) internal {\n require(amount > 0, \"Cannot stake 0\");\n\n uint240 rewardRate = _findDurationRate(duration);\n require(rewardRate > 0, \"Invalid duration\"); // we couldn't find the rate that correspond to the passed duration\n\n _stake(staker, USER_STAKE_TYPE, duration, rewardRate, amount);\n // transfer in the token so that we can stake the correct amount\n stakingToken.safeTransferFrom(staker, address(this), amount);\n }\n\n modifier requireLiquidity() {\n // we need to have enough balance to cover the rewards after the operation is complete\n _;\n require(\n stakingToken.balanceOf(address(this)) >= totalOutstanding,\n \"Insufficient rewards\"\n );\n }\n\n /* ========== VIEWS ========== */\n\n function getAllDurations() external view returns (uint256[] memory) {\n return durations;\n }\n\n function getAllRates() external view returns (uint256[] memory) {\n return rates;\n }\n\n /**\n * @dev Return all the stakes paid and unpaid for a given user\n * @param account Address of the account that we want to look up\n */\n function getAllStakes(address account)\n external\n view\n returns (Stake[] memory)\n {\n return userStakes[account];\n }\n\n /**\n * @dev Find the rate that corresponds to a given duration\n * @param _duration Number of seconds\n */\n function durationRewardRate(uint256 _duration)\n external\n view\n returns (uint256)\n {\n return _findDurationRate(_duration);\n }\n\n /**\n * @dev Has the airdropped stake already been claimed\n */\n function airDroppedStakeClaimed(address account, uint8 stakeType)\n external\n view\n returns (bool)\n {\n return _airDroppedStakeClaimed(account, stakeType);\n }\n\n /**\n * @dev Calculate all the staked value a user has put into the contract,\n * rewards not included\n * @param account Address of the account that we want to look up\n */\n function totalStaked(address account)\n external\n view\n returns (uint256 total)\n {\n Stake[] storage stakes = userStakes[account];\n\n for (uint256 i = 0; i < stakes.length; i++) {\n if (!stakes[i].paid) {\n total = total.add(stakes[i].amount);\n }\n }\n }\n\n /**\n * @dev Calculate all the rewards a user can expect to receive.\n * @param account Address of the account that we want to look up\n */\n function totalExpectedRewards(address account)\n external\n view\n returns (uint256)\n {\n return _totalExpectedRewards(userStakes[account]);\n }\n\n /**\n * @dev Calculate all current holdings of a user: staked value + prorated rewards\n * @param account Address of the account that we want to look up\n */\n function totalCurrentHoldings(address account)\n external\n view\n returns (uint256 total)\n {\n Stake[] storage stakes = userStakes[account];\n\n for (uint256 i = 0; i < stakes.length; i++) {\n Stake storage stake = stakes[i];\n if (stake.paid) {\n continue;\n } else if (stake.end < block.timestamp) {\n total = total.add(_totalExpected(stake));\n } else {\n //calcualte the precentage accrued in term of rewards\n total = total.add(\n stake.amount.add(\n stake.amount.mulTruncate(stake.rate).mulTruncate(\n stake\n .duration\n .sub(stake.end.sub(block.timestamp))\n .divPrecisely(stake.duration)\n )\n )\n );\n }\n }\n }\n\n /* ========== MUTATIVE FUNCTIONS ========== */\n\n /**\n * @dev Make a preapproved stake for the user, this is a presigned voucher that the user can redeem either from\n * an airdrop or a compensation program.\n * Only 1 of each type is allowed per user. The proof must match the root hash\n * @param index Number that is zero base index of the stake in the payout entry\n * @param stakeType Number that represent the type of the stake, must not be 0 which is user stake\n * @param duration Number of seconds this stake will be held for\n * @param rate Rate(0.3 is 30%) of reward for this stake in 1e18, uint240 to fit the bool and type in struct Stake\n * @param amount Number of tokens to stake in 1e18\n * @param merkleProof Array of proofs for that amount\n */\n function airDroppedStake(\n uint256 index,\n uint8 stakeType,\n uint256 duration,\n uint256 rate,\n uint256 amount,\n bytes32[] calldata merkleProof\n ) external requireLiquidity {\n require(stakeType != USER_STAKE_TYPE, \"Cannot be normal staking\");\n require(rate < uint240(-1), \"Max rate exceeded\");\n require(index < 2**merkleProof.length, \"Invalid index\");\n DropRoot storage dropRoot = dropRoots[stakeType];\n require(merkleProof.length == dropRoot.depth, \"Invalid proof\");\n\n // Compute the merkle root\n bytes32 node = keccak256(\n abi.encodePacked(\n index,\n stakeType,\n address(this),\n msg.sender,\n duration,\n rate,\n amount\n )\n );\n uint256 path = index;\n for (uint16 i = 0; i < merkleProof.length; i++) {\n if ((path & 0x01) == 1) {\n node = keccak256(abi.encodePacked(merkleProof[i], node));\n } else {\n node = keccak256(abi.encodePacked(node, merkleProof[i]));\n }\n path /= 2;\n }\n\n // Check the merkle proof\n require(node == dropRoot.hash, \"Stake not approved\");\n\n // verify that we haven't already staked\n require(\n !_airDroppedStakeClaimed(msg.sender, stakeType),\n \"Already staked\"\n );\n\n _stake(msg.sender, stakeType, duration, uint240(rate), amount);\n }\n\n /**\n * @dev Stake an approved amount of staking token into the contract.\n * User must have already approved the contract for specified amount.\n * @param amount Number of tokens to stake in 1e18\n * @param duration Number of seconds this stake will be held for\n */\n function stake(uint256 amount, uint256 duration) external requireLiquidity {\n // no checks are performed in this function since those are already present in _stakeWithChecks\n _stakeWithChecks(msg.sender, amount, duration);\n }\n\n /**\n * @dev Stake an approved amount of staking token into the contract. This function\n * can only be called by OGN token contract.\n * @param staker Address of the account that is creating the stake\n * @param amount Number of tokens to stake in 1e18\n * @param duration Number of seconds this stake will be held for\n */\n function stakeWithSender(\n address staker,\n uint256 amount,\n uint256 duration\n ) external returns (bool) {\n require(\n msg.sender == address(stakingToken),\n \"Only token contract can make this call\"\n );\n\n _stakeWithChecks(staker, amount, duration);\n return true;\n }\n\n /**\n * @dev Exit out of all possible stakes\n */\n function exit() external requireLiquidity {\n Stake[] storage stakes = userStakes[msg.sender];\n require(stakes.length > 0, \"Nothing staked\");\n\n uint256 totalWithdraw = 0;\n uint256 stakedAmount = 0;\n uint256 l = stakes.length;\n do {\n Stake storage exitStake = stakes[l - 1];\n // stop on the first ended stake that's already been paid\n if (exitStake.end < block.timestamp && exitStake.paid) {\n break;\n }\n //might not be ended\n if (exitStake.end < block.timestamp) {\n //we are paying out the stake\n exitStake.paid = true;\n totalWithdraw = totalWithdraw.add(_totalExpected(exitStake));\n stakedAmount = stakedAmount.add(exitStake.amount);\n }\n l--;\n } while (l > 0);\n require(totalWithdraw > 0, \"All stakes in lock-up\");\n\n totalOutstanding = totalOutstanding.sub(totalWithdraw);\n emit Withdrawn(msg.sender, totalWithdraw, stakedAmount);\n stakingToken.safeTransfer(msg.sender, totalWithdraw);\n }\n\n /* ========== MODIFIERS ========== */\n\n function setPaused(bool _paused) external onlyGovernor {\n paused = _paused;\n emit Paused(msg.sender, paused);\n }\n\n /**\n * @dev Set new durations and rates will not effect existing stakes\n * @param _durations Array of durations in seconds\n * @param _rates Array of rates that corresponds to the durations (0.01 is 1%) in 1e18\n */\n function setDurationRates(\n uint256[] calldata _durations,\n uint256[] calldata _rates\n ) external onlyGovernor {\n _setDurationRates(_durations, _rates);\n }\n\n /**\n * @dev Set air drop root for a specific stake type\n * @param _stakeType Type of staking must be greater than 0\n * @param _rootHash Root hash of the Merkle Tree\n * @param _proofDepth Depth of the Merklke Tree\n */\n function setAirDropRoot(\n uint8 _stakeType,\n bytes32 _rootHash,\n uint256 _proofDepth\n ) external onlyGovernor {\n require(_stakeType != USER_STAKE_TYPE, \"Cannot be normal staking\");\n dropRoots[_stakeType].hash = _rootHash;\n dropRoots[_stakeType].depth = _proofDepth;\n emit NewAirDropRootHash(_stakeType, _rootHash, _proofDepth);\n }\n\n /* ========== EVENTS ========== */\n\n event Staked(\n address indexed user,\n uint256 amount,\n uint256 duration,\n uint256 rate\n );\n event Withdrawn(address indexed user, uint256 amount, uint256 stakedAmount);\n event Paused(address indexed user, bool yes);\n event NewDurations(address indexed user, uint256[] durations);\n event NewRates(address indexed user, uint256[] rates);\n event NewAirDropRootHash(\n uint8 stakeType,\n bytes32 rootHash,\n uint256 proofDepth\n );\n}\n" + }, + "contracts/proxies/InitializeGovernedUpgradeabilityProxy.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { Governable } from \"../governance/Governable.sol\";\nimport {\n BaseUpgradeabilityProxy\n} from \"@openzeppelin/upgrades/contracts/upgradeability/BaseUpgradeabilityProxy.sol\";\n\n/**\n * @title BaseGovernedUpgradeabilityProxy\n * @dev This contract combines an upgradeability proxy with our governor system\n * @author Origin Protocol Inc\n */\ncontract InitializeGovernedUpgradeabilityProxy is\n Governable,\n BaseUpgradeabilityProxy\n{\n /**\n * @dev Contract initializer with Governor enforcement\n * @param _logic Address of the initial implementation.\n * @param _initGovernor Address of the initial Governor.\n * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.\n * It should include the signature and the parameters of the function to be called, as described in\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\n * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\n */\n function initialize(\n address _logic,\n address _initGovernor,\n bytes memory _data\n ) public payable onlyGovernor {\n require(_implementation() == address(0));\n assert(\n IMPLEMENTATION_SLOT ==\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1)\n );\n _changeGovernor(_initGovernor);\n _setImplementation(_logic);\n if (_data.length > 0) {\n (bool success, ) = _logic.delegatecall(_data);\n require(success);\n }\n }\n\n /**\n * @return The address of the proxy admin/it's also the governor.\n */\n function admin() external view returns (address) {\n return _governor();\n }\n\n /**\n * @return The address of the implementation.\n */\n function implementation() external view returns (address) {\n return _implementation();\n }\n\n /**\n * @dev Upgrade the backing implementation of the proxy.\n * Only the admin can call this function.\n * @param newImplementation Address of the new implementation.\n */\n function upgradeTo(address newImplementation) external onlyGovernor {\n _upgradeTo(newImplementation);\n }\n\n /**\n * @dev Upgrade the backing implementation of the proxy and call a function\n * on the new implementation.\n * This is useful to initialize the proxied contract.\n * @param newImplementation Address of the new implementation.\n * @param data Data to send as msg.data in the low level call.\n * It should include the signature and the parameters of the function to be called, as described in\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data)\n external\n payable\n onlyGovernor\n {\n _upgradeTo(newImplementation);\n (bool success, ) = newImplementation.delegatecall(data);\n require(success);\n }\n}\n" + }, + "@openzeppelin/upgrades/contracts/upgradeability/BaseUpgradeabilityProxy.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport './Proxy.sol';\nimport '../utils/Address.sol';\n\n/**\n * @title BaseUpgradeabilityProxy\n * @dev This contract implements a proxy that allows to change the\n * implementation address to which it will delegate.\n * Such a change is called an implementation upgrade.\n */\ncontract BaseUpgradeabilityProxy is Proxy {\n /**\n * @dev Emitted when the implementation is upgraded.\n * @param implementation Address of the new implementation.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation.\n * @return Address of the current implementation\n */\n function _implementation() internal view returns (address impl) {\n bytes32 slot = IMPLEMENTATION_SLOT;\n assembly {\n impl := sload(slot)\n }\n }\n\n /**\n * @dev Upgrades the proxy to a new implementation.\n * @param newImplementation Address of the new implementation.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation address of the proxy.\n * @param newImplementation Address of the new implementation.\n */\n function _setImplementation(address newImplementation) internal {\n require(OpenZeppelinUpgradesAddress.isContract(newImplementation), \"Cannot set a proxy implementation to a non-contract address\");\n\n bytes32 slot = IMPLEMENTATION_SLOT;\n\n assembly {\n sstore(slot, newImplementation)\n }\n }\n}\n" + }, + "@openzeppelin/upgrades/contracts/upgradeability/Proxy.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @title Proxy\n * @dev Implements delegation of calls to other contracts, with proper\n * forwarding of return values and bubbling of failures.\n * It defines a fallback function that delegates all calls to the address\n * returned by the abstract _implementation() internal function.\n */\ncontract Proxy {\n /**\n * @dev Fallback function.\n * Implemented entirely in `_fallback`.\n */\n function () payable external {\n _fallback();\n }\n\n /**\n * @return The Address of the implementation.\n */\n function _implementation() internal view returns (address);\n\n /**\n * @dev Delegates execution to an implementation contract.\n * This is a low level function that doesn't return to its internal call site.\n * It will return to the external caller whatever the implementation returns.\n * @param implementation Address to delegate.\n */\n function _delegate(address implementation) internal {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize)\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize)\n\n switch result\n // delegatecall returns 0 on error.\n case 0 { revert(0, returndatasize) }\n default { return(0, returndatasize) }\n }\n }\n\n /**\n * @dev Function that is run as the first thing in the fallback function.\n * Can be redefined in derived contracts to add functionality.\n * Redefinitions must call super._willFallback().\n */\n function _willFallback() internal {\n }\n\n /**\n * @dev fallback implementation.\n * Extracted to enable manual triggering.\n */\n function _fallback() internal {\n _willFallback();\n _delegate(_implementation());\n }\n}\n" + }, + "@openzeppelin/upgrades/contracts/utils/Address.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * Utility library of inline functions on addresses\n *\n * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/utils/Address.sol\n * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts\n * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the\n * build/artifacts folder) as well as the vanilla Address implementation from an openzeppelin version.\n */\nlibrary OpenZeppelinUpgradesAddress {\n /**\n * Returns whether the target address is a contract\n * @dev This function will return false if invoked during the constructor of a contract,\n * as the code is not actually created until after the constructor finishes.\n * @param account address of the account to check\n * @return whether the target address is a contract\n */\n function isContract(address account) internal view returns (bool) {\n uint256 size;\n // XXX Currently there is no better way to check if there is a contract in an address\n // than to check the size of the code at that address.\n // See https://ethereum.stackexchange.com/a/14016/36603\n // for more details about how this works.\n // TODO Check this again before the Serenity release, because all addresses will be\n // contracts then.\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n}\n" + }, + "contracts/proxies/Proxies.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n InitializeGovernedUpgradeabilityProxy\n} from \"./InitializeGovernedUpgradeabilityProxy.sol\";\n\n/**\n * @notice OUSDProxy delegates calls to an OUSD implementation\n */\ncontract OUSDProxy is InitializeGovernedUpgradeabilityProxy {\n\n}\n\n/**\n * @notice VaultProxy delegates calls to a Vault implementation\n */\ncontract VaultProxy is InitializeGovernedUpgradeabilityProxy {\n\n}\n\n/**\n * @notice CompoundStrategyProxy delegates calls to a CompoundStrategy implementation\n */\ncontract CompoundStrategyProxy is InitializeGovernedUpgradeabilityProxy {\n\n}\n\n/**\n * @notice ThreePoolStrategyProxy delegates calls to a ThreePoolStrategy implementation\n */\ncontract ThreePoolStrategyProxy is InitializeGovernedUpgradeabilityProxy {\n\n}\n" + }, + "contracts/oracle/MixOracle.sol": { + "content": "// DEPRECATED - This contract is no longer used in production\n\npragma solidity 0.5.11;\n\n/**\n * @title OUSD MixOracle Contract\n * @notice The MixOracle pulls exchange rate from multiple oracles and returns\n * min and max values.\n * @author Origin Protocol Inc\n */\nimport { IPriceOracle } from \"../interfaces/IPriceOracle.sol\";\nimport { IEthUsdOracle } from \"../interfaces/IEthUsdOracle.sol\";\nimport { IMinMaxOracle } from \"../interfaces/IMinMaxOracle.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\ncontract MixOracle is IMinMaxOracle, Governable {\n event DriftsUpdated(uint256 _minDrift, uint256 _maxDrift);\n event EthUsdOracleRegistered(address _oracle);\n event EthUsdOracleDeregistered(address _oracle);\n event TokenOracleRegistered(\n string symbol,\n address[] ethOracles,\n address[] usdOracles\n );\n\n address[] public ethUsdOracles;\n\n struct MixConfig {\n address[] usdOracles;\n address[] ethOracles;\n }\n\n mapping(bytes32 => MixConfig) configs;\n\n uint256 constant MAX_INT = 2**256 - 1;\n uint256 public maxDrift;\n uint256 public minDrift;\n\n constructor(uint256 _maxDrift, uint256 _minDrift) public {\n maxDrift = _maxDrift;\n minDrift = _minDrift;\n emit DriftsUpdated(_minDrift, _maxDrift);\n }\n\n function setMinMaxDrift(uint256 _minDrift, uint256 _maxDrift)\n public\n onlyGovernor\n {\n minDrift = _minDrift;\n maxDrift = _maxDrift;\n emit DriftsUpdated(_minDrift, _maxDrift);\n }\n\n /**\n * @notice Adds an oracle to the list of oracles to pull data from.\n * @param oracle Address of an oracle that implements the IEthUsdOracle interface.\n **/\n function registerEthUsdOracle(address oracle) public onlyGovernor {\n for (uint256 i = 0; i < ethUsdOracles.length; i++) {\n require(ethUsdOracles[i] != oracle, \"Oracle already registered.\");\n }\n ethUsdOracles.push(oracle);\n emit EthUsdOracleRegistered(oracle);\n }\n\n /**\n * @notice Removes an oracle to the list of oracles to pull data from.\n * @param oracle Address of an oracle that implements the IEthUsdOracle interface.\n **/\n function unregisterEthUsdOracle(address oracle) public onlyGovernor {\n for (uint256 i = 0; i < ethUsdOracles.length; i++) {\n if (ethUsdOracles[i] == oracle) {\n // swap with the last element of the array, and then delete last element (could be itself)\n ethUsdOracles[i] = ethUsdOracles[ethUsdOracles.length - 1];\n delete ethUsdOracles[ethUsdOracles.length - 1];\n emit EthUsdOracleDeregistered(oracle);\n ethUsdOracles.pop();\n return;\n }\n }\n revert(\"Oracle not found\");\n }\n\n /**\n * @notice Adds an oracle to the list of oracles to pull data from.\n * @param ethOracles Addresses of oracles that implements the IEthUsdOracle interface and answers for this asset\n * @param usdOracles Addresses of oracles that implements the IPriceOracle interface and answers for this asset\n **/\n function registerTokenOracles(\n string calldata symbol,\n address[] calldata ethOracles,\n address[] calldata usdOracles\n ) external onlyGovernor {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n config.ethOracles = ethOracles;\n config.usdOracles = usdOracles;\n emit TokenOracleRegistered(symbol, ethOracles, usdOracles);\n }\n\n /**\n * @notice Returns the min price of an asset in USD.\n * @return symbol Asset symbol. Example: \"DAI\"\n * @return price Min price from all the oracles, in USD with 8 decimal digits.\n **/\n function priceMin(string calldata symbol)\n external\n view\n returns (uint256 price)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n uint256 ep;\n uint256 p; //holder variables\n price = MAX_INT;\n if (config.ethOracles.length > 0) {\n ep = MAX_INT;\n for (uint256 i = 0; i < config.ethOracles.length; i++) {\n p = IEthUsdOracle(config.ethOracles[i]).tokEthPrice(symbol);\n if (ep > p) {\n ep = p;\n }\n }\n price = ep;\n ep = MAX_INT;\n for (uint256 i = 0; i < ethUsdOracles.length; i++) {\n p = IEthUsdOracle(ethUsdOracles[i]).ethUsdPrice();\n if (ep > p) {\n ep = p;\n }\n }\n if (price != MAX_INT && ep != MAX_INT) {\n // tokEthPrice has precision of 8 which ethUsdPrice has precision of 6\n // we want precision of 8\n price = (price * ep) / 1e6;\n }\n }\n\n if (config.usdOracles.length > 0) {\n for (uint256 i = 0; i < config.usdOracles.length; i++) {\n // upscale by 2 since price oracles are precision 6\n p = IPriceOracle(config.usdOracles[i]).price(symbol) * 1e2;\n if (price > p) {\n price = p;\n }\n }\n }\n require(price <= maxDrift, \"Price exceeds maxDrift\");\n require(price >= minDrift, \"Price below minDrift\");\n require(\n price != MAX_INT,\n \"None of our oracles returned a valid min price!\"\n );\n }\n\n /**\n * @notice Returns max price of an asset in USD.\n * @return symbol Asset symbol. Example: \"DAI\"\n * @return price Max price from all the oracles, in USD with 8 decimal digits.\n **/\n function priceMax(string calldata symbol)\n external\n view\n returns (uint256 price)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n uint256 ep;\n uint256 p; //holder variables\n price = 0;\n if (config.ethOracles.length > 0) {\n ep = 0;\n for (uint256 i = 0; i < config.ethOracles.length; i++) {\n p = IEthUsdOracle(config.ethOracles[i]).tokEthPrice(symbol);\n if (ep < p) {\n ep = p;\n }\n }\n price = ep;\n ep = 0;\n for (uint256 i = 0; i < ethUsdOracles.length; i++) {\n p = IEthUsdOracle(ethUsdOracles[i]).ethUsdPrice();\n if (ep < p) {\n ep = p;\n }\n }\n if (price != 0 && ep != 0) {\n // tokEthPrice has precision of 8 which ethUsdPrice has precision of 6\n // we want precision of 8\n price = (price * ep) / 1e6;\n }\n }\n\n if (config.usdOracles.length > 0) {\n for (uint256 i = 0; i < config.usdOracles.length; i++) {\n // upscale by 2 since price oracles are precision 6\n p = IPriceOracle(config.usdOracles[i]).price(symbol) * 1e2;\n if (price < p) {\n price = p;\n }\n }\n }\n\n require(price <= maxDrift, \"Price exceeds maxDrift\");\n require(price >= minDrift, \"Price below minDrift\");\n require(price != 0, \"None of our oracles returned a valid max price!\");\n }\n\n /**\n * @notice Returns the length of the usdOracles array for a given token\n * @param symbol Asset symbol. Example: \"DAI\"\n * @return length of the USD oracles array\n **/\n function getTokenUSDOraclesLength(string calldata symbol)\n external\n view\n returns (uint256)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n return config.usdOracles.length;\n }\n\n /**\n * @notice Returns the address of a specific USD oracle\n * @param symbol Asset symbol. Example: \"DAI\"\n * @param idx Index of the array value to return\n * @return address of the oracle\n **/\n function getTokenUSDOracle(string calldata symbol, uint256 idx)\n external\n view\n returns (address)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n return config.usdOracles[idx];\n }\n\n /**\n * @notice Returns the length of the ethOracles array for a given token\n * @param symbol Asset symbol. Example: \"DAI\"\n * @return length of the ETH oracles array\n **/\n function getTokenETHOraclesLength(string calldata symbol)\n external\n view\n returns (uint256)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n return config.ethOracles.length;\n }\n\n /**\n * @notice Returns the address of a specific ETH oracle\n * @param symbol Asset symbol. Example: \"DAI\"\n * @param idx Index of the array value to return\n * @return address of the oracle\n **/\n function getTokenETHOracle(string calldata symbol, uint256 idx)\n external\n view\n returns (address)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n return config.ethOracles[idx];\n }\n}\n" + }, + "contracts/interfaces/IPriceOracle.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IPriceOracle {\n /**\n * @dev returns the asset price in USD, 6 decimal digits.\n * Compatible with the Open Price Feed.\n */\n function price(string calldata symbol) external view returns (uint256);\n}\n" + }, + "contracts/interfaces/IEthUsdOracle.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IEthUsdOracle {\n /**\n * @notice Returns ETH price in USD.\n * @return Price in USD with 6 decimal digits.\n */\n function ethUsdPrice() external view returns (uint256);\n\n /**\n * @notice Returns token price in USD.\n * @param symbol. Asset symbol. For ex. \"DAI\".\n * @return Price in USD with 6 decimal digits.\n */\n function tokUsdPrice(string calldata symbol)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the asset price in ETH.\n * @param symbol. Asset symbol. For ex. \"DAI\".\n * @return Price in ETH with 8 decimal digits.\n */\n function tokEthPrice(string calldata symbol)\n external\n view\n returns (uint256);\n}\n\ninterface IViewEthUsdOracle {\n /**\n * @notice Returns ETH price in USD.\n * @return Price in USD with 6 decimal digits.\n */\n function ethUsdPrice() external view returns (uint256);\n\n /**\n * @notice Returns token price in USD.\n * @param symbol. Asset symbol. For ex. \"DAI\".\n * @return Price in USD with 6 decimal digits.\n */\n function tokUsdPrice(string calldata symbol)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the asset price in ETH.\n * @param symbol. Asset symbol. For ex. \"DAI\".\n * @return Price in ETH with 8 decimal digits.\n */\n function tokEthPrice(string calldata symbol)\n external\n view\n returns (uint256);\n}\n" + }, + "contracts/interfaces/IMinMaxOracle.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IMinMaxOracle {\n //Assuming 8 decimals\n function priceMin(string calldata symbol) external view returns (uint256);\n\n function priceMax(string calldata symbol) external view returns (uint256);\n}\n" + }, + "contracts/mocks/MockOracle.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../interfaces/IPriceOracle.sol\";\nimport \"../interfaces/IMinMaxOracle.sol\";\n\n/**\n * Mock of both price Oracle and min max oracles\n */\ncontract MockOracle is IPriceOracle, IMinMaxOracle {\n mapping(bytes32 => uint256) prices;\n mapping(bytes32 => uint256[]) pricesMinMax;\n uint256 ethMin;\n uint256 ethMax;\n\n /**\n * @dev returns the asset price in USD, 6 decimal digits.\n * Compatible with the Open Price Feed.\n */\n function price(string calldata symbol) external view returns (uint256) {\n return prices[keccak256(abi.encodePacked(symbol))];\n }\n\n /**\n * @dev sets the price of the asset in USD, 6 decimal digits\n *\n */\n function setPrice(string calldata symbol, uint256 _price) external {\n prices[keccak256(abi.encodePacked(symbol))] = _price;\n }\n\n /**\n * @dev sets the min and max price of ETH in USD, 6 decimal digits\n *\n */\n function setEthPriceMinMax(uint256 _min, uint256 _max) external {\n ethMin = _min;\n ethMax = _max;\n }\n\n /**\n * @dev sets the prices Min Max for a specific symbol in ETH, 8 decimal digits\n *\n */\n function setTokPriceMinMax(\n string calldata symbol,\n uint256 _min,\n uint256 _max\n ) external {\n pricesMinMax[keccak256(abi.encodePacked(symbol))] = [_min, _max];\n }\n\n /**\n * @dev get the price of asset in ETH, 8 decimal digits.\n */\n function priceMin(string calldata symbol) external view returns (uint256) {\n uint256[] storage pMinMax = pricesMinMax[keccak256(\n abi.encodePacked(symbol)\n )];\n return (pMinMax[0] * ethMin) / 1e6;\n }\n\n /**\n * @dev get the price of asset in USD, 8 decimal digits.\n * Not needed for now\n */\n function priceMax(string calldata symbol) external view returns (uint256) {\n uint256[] storage pMinMax = pricesMinMax[keccak256(\n abi.encodePacked(symbol)\n )];\n return (pMinMax[1] * ethMax) / 1e6;\n }\n}\n" + }, + "contracts/oracle/ChainlinkOracle.sol": { + "content": "// DEPRECATED - This contract is no longer used in production\npragma solidity 0.5.11;\n\n/**\n * @title OUSD ChainlinkOracle Contract\n * @author Origin Protocol Inc\n */\nimport \"../interfaces/chainlink/AggregatorV3Interface.sol\";\nimport { IPriceOracle } from \"../interfaces/IPriceOracle.sol\";\nimport { IEthUsdOracle } from \"../interfaces/IEthUsdOracle.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\ncontract ChainlinkOracle is IEthUsdOracle, IPriceOracle, Governable {\n event FeedRegistered(address _feed, string _symbol, bool _directToUsd);\n\n address ethFeed;\n\n struct FeedConfig {\n address feed;\n uint8 decimals;\n bool directToUsd;\n }\n\n mapping(bytes32 => FeedConfig) feeds;\n\n uint8 ethDecimals;\n\n string constant ethSymbol = \"ETH\";\n bytes32 constant ethHash = keccak256(abi.encodePacked(ethSymbol));\n\n constructor(address ethFeed_) public {\n ethFeed = ethFeed_;\n ethDecimals = AggregatorV3Interface(ethFeed_).decimals();\n }\n\n function registerFeed(\n address feed,\n string memory symbol,\n bool directToUsd\n ) public onlyGovernor {\n FeedConfig storage config = feeds[keccak256(abi.encodePacked(symbol))];\n\n config.feed = feed;\n config.decimals = AggregatorV3Interface(feed).decimals();\n config.directToUsd = directToUsd;\n\n emit FeedRegistered(feed, symbol, directToUsd);\n }\n\n function getLatestPrice(address feed) internal view returns (int256) {\n (\n uint80 roundID,\n int256 price,\n uint256 startedAt,\n uint256 timeStamp,\n uint80 answeredInRound\n ) = AggregatorV3Interface(feed).latestRoundData();\n // silence\n roundID;\n startedAt;\n timeStamp;\n answeredInRound;\n return price;\n }\n\n function ethUsdPrice() external view returns (uint256) {\n return (uint256(getLatestPrice(ethFeed)) /\n (uint256(10)**(ethDecimals - 6)));\n }\n\n function tokUsdPrice(string calldata symbol)\n external\n view\n returns (uint256)\n {\n bytes32 tokenSymbolHash = keccak256(abi.encodePacked(symbol));\n FeedConfig storage config = feeds[tokenSymbolHash];\n int256 tPrice = getLatestPrice(config.feed);\n\n require(config.directToUsd, \"Price is not direct to usd\");\n require(tPrice > 0, \"Price must be greater than zero\");\n return uint256(tPrice);\n }\n\n function tokEthPrice(string calldata symbol)\n external\n view\n returns (uint256)\n {\n bytes32 tokenSymbolHash = keccak256(abi.encodePacked(symbol));\n FeedConfig storage config = feeds[tokenSymbolHash];\n int256 tPrice = getLatestPrice(config.feed);\n\n require(!config.directToUsd, \"Price is not in terms of ETH\");\n require(tPrice > 0, \"Price must be greater than zero\");\n //attempt to return 8 digit precision here\n return uint256(tPrice) / (uint256(10)**(config.decimals - 8));\n }\n\n // This actually calculate the latest price from outside oracles\n // It's a view but substantially more costly in terms of calculation\n function price(string calldata symbol) external view returns (uint256) {\n bytes32 tokenSymbolHash = keccak256(abi.encodePacked(symbol));\n\n if (ethHash == tokenSymbolHash) {\n return (uint256(getLatestPrice(ethFeed)) /\n (uint256(10)**(ethDecimals - 6)));\n } else {\n FeedConfig storage config = feeds[tokenSymbolHash];\n int256 tPrice = getLatestPrice(config.feed);\n\n if (config.directToUsd) {\n require(tPrice > 0, \"Price must be greater than zero\");\n return uint256(tPrice);\n } else {\n int256 ethPrice = getLatestPrice(ethFeed); // grab the eth price from the open oracle\n require(\n tPrice > 0 && ethPrice > 0,\n \"Both eth and price must be greater than zero\"\n );\n //not actually sure why it's 6 units here, this is just to match with openoracle for now\n return\n mul(uint256(tPrice), uint256(ethPrice)) /\n (uint256(10)**(ethDecimals + config.decimals - 6));\n }\n }\n }\n\n /// @dev Overflow proof multiplication\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"multiplication overflow\");\n return c;\n }\n}\n" + }, + "contracts/interfaces/chainlink/AggregatorV3Interface.sol": { + "content": "pragma solidity ^0.5.11;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "contracts/oracle/OracleRouter.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../interfaces/chainlink/AggregatorV3Interface.sol\";\nimport { IOracle } from \"../interfaces/IOracle.sol\";\n\ncontract OracleRouterBase is IOracle {\n uint256 constant MIN_DRIFT = uint256(70000000);\n uint256 constant MAX_DRIFT = uint256(130000000);\n\n /**\n * @dev The price feed contract to use for a particular asset.\n * @param asset address of the asset\n */\n function feed(address asset) internal view returns (address);\n\n /**\n * @notice Returns the total price in 8 digit USD for a given asset.\n * @param asset address of the asset\n * @return uint256 USD price of 1 of the asset, in 8 decimal fixed\n */\n function price(address asset) external view returns (uint256) {\n address _feed = feed(asset);\n require(_feed != address(0), \"Asset not available\");\n (\n uint80 roundID,\n int256 _iprice,\n uint256 startedAt,\n uint256 timeStamp,\n uint80 answeredInRound\n ) = AggregatorV3Interface(_feed).latestRoundData();\n uint256 _price = uint256(_iprice);\n require(_price <= MAX_DRIFT, \"Oracle: Price exceeds max\");\n require(_price >= MIN_DRIFT, \"Oracle: Price under min\");\n return uint256(_price);\n }\n}\n\ncontract OracleRouter is OracleRouterBase {\n /**\n * @dev The price feed contract to use for a particular asset.\n * @param asset address of the asset\n */\n function feed(address asset) internal view returns (address) {\n // DAI\n if (asset == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) {\n return address(0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9);\n // USDC\n } else if (\n asset == address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)\n ) {\n return address(0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6);\n // USDT\n } else if (\n asset == address(0xdAC17F958D2ee523a2206206994597C13D831ec7)\n ) {\n return address(0x3E7d1eAB13ad0104d2750B8863b489D65364e32D);\n } else {\n require(false, \"Asset not available\");\n }\n }\n}\n\ncontract OracleRouterDev is OracleRouterBase {\n mapping(address => address) public assetToFeed;\n\n function setFeed(address _asset, address _feed) external {\n assetToFeed[_asset] = _feed;\n }\n\n /**\n * @dev The price feed contract to use for a particular asset.\n * @param asset address of the asset\n */\n function feed(address asset) internal view returns (address) {\n return assetToFeed[asset];\n }\n}\n" + }, + "contracts/vault/VaultCore.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Vault Contract\n * @notice The Vault contract stores assets. On a deposit, OUSD will be minted\n and sent to the depositor. On a withdrawal, OUSD will be burned and\n assets will be sent to the withdrawer. The Vault accepts deposits of\n interest form yield bearing strategies which will modify the supply\n of OUSD.\n * @author Origin Protocol Inc\n */\n\nimport \"./VaultStorage.sol\";\nimport { IOracle } from \"../interfaces/IOracle.sol\";\nimport { IVault } from \"../interfaces/IVault.sol\";\nimport { IBuyback } from \"../interfaces/IBuyback.sol\";\n\ncontract VaultCore is VaultStorage {\n uint256 constant MAX_UINT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n\n /**\n * @dev Verifies that the rebasing is not paused.\n */\n modifier whenNotRebasePaused() {\n require(!rebasePaused, \"Rebasing paused\");\n _;\n }\n\n /**\n * @dev Verifies that the deposits are not paused.\n */\n modifier whenNotCapitalPaused() {\n require(!capitalPaused, \"Capital paused\");\n _;\n }\n\n /**\n * @dev Deposit a supported asset and mint OUSD.\n * @param _asset Address of the asset being deposited\n * @param _amount Amount of the asset being deposited\n * @param _minimumOusdAmount Minimum OUSD to mint\n */\n function mint(\n address _asset,\n uint256 _amount,\n uint256 _minimumOusdAmount\n ) external whenNotCapitalPaused nonReentrant {\n require(assets[_asset].isSupported, \"Asset is not supported\");\n require(_amount > 0, \"Amount must be greater than 0\");\n\n uint256 price = IOracle(priceProvider).price(_asset);\n if (price > 1e8) {\n price = 1e8;\n }\n uint256 assetDecimals = Helpers.getDecimals(_asset);\n uint256 unitAdjustedDeposit = _amount.scaleBy(int8(18 - assetDecimals));\n uint256 priceAdjustedDeposit = _amount.mulTruncateScale(\n price.scaleBy(int8(10)), // 18-8 because oracles have 8 decimals precision\n 10**assetDecimals\n );\n\n if (_minimumOusdAmount > 0) {\n require(\n priceAdjustedDeposit >= _minimumOusdAmount,\n \"Mint amount lower than minimum\"\n );\n }\n\n emit Mint(msg.sender, priceAdjustedDeposit);\n\n // Rebase must happen before any transfers occur.\n if (unitAdjustedDeposit >= rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n\n // Mint matching OUSD\n oUSD.mint(msg.sender, priceAdjustedDeposit);\n\n // Transfer the deposited coins to the vault\n IERC20 asset = IERC20(_asset);\n asset.safeTransferFrom(msg.sender, address(this), _amount);\n\n if (unitAdjustedDeposit >= autoAllocateThreshold) {\n _allocate();\n }\n }\n\n /**\n * @dev Mint for multiple assets in the same call.\n * @param _assets Addresses of assets being deposited\n * @param _amounts Amount of each asset at the same index in the _assets\n * to deposit.\n * @param _minimumOusdAmount Minimum OUSD to mint\n */\n function mintMultiple(\n address[] calldata _assets,\n uint256[] calldata _amounts,\n uint256 _minimumOusdAmount\n ) external whenNotCapitalPaused nonReentrant {\n require(_assets.length == _amounts.length, \"Parameter length mismatch\");\n\n uint256 unitAdjustedTotal = 0;\n uint256 priceAdjustedTotal = 0;\n uint256[] memory assetPrices = _getAssetPrices(false);\n for (uint256 j = 0; j < _assets.length; j++) {\n // In memoriam\n require(assets[_assets[j]].isSupported, \"Asset is not supported\");\n require(_amounts[j] > 0, \"Amount must be greater than 0\");\n for (uint256 i = 0; i < allAssets.length; i++) {\n if (_assets[j] == allAssets[i]) {\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\n uint256 price = assetPrices[i];\n if (price > 1e18) {\n price = 1e18;\n }\n unitAdjustedTotal = unitAdjustedTotal.add(\n _amounts[j].scaleBy(int8(18 - assetDecimals))\n );\n priceAdjustedTotal = priceAdjustedTotal.add(\n _amounts[j].mulTruncateScale(price, 10**assetDecimals)\n );\n }\n }\n }\n\n if (_minimumOusdAmount > 0) {\n require(\n priceAdjustedTotal >= _minimumOusdAmount,\n \"Mint amount lower than minimum\"\n );\n }\n\n emit Mint(msg.sender, priceAdjustedTotal);\n\n // Rebase must happen before any transfers occur.\n if (unitAdjustedTotal >= rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n\n oUSD.mint(msg.sender, priceAdjustedTotal);\n\n for (uint256 i = 0; i < _assets.length; i++) {\n IERC20 asset = IERC20(_assets[i]);\n asset.safeTransferFrom(msg.sender, address(this), _amounts[i]);\n }\n\n if (unitAdjustedTotal >= autoAllocateThreshold) {\n _allocate();\n }\n }\n\n /**\n * @dev Withdraw a supported asset and burn OUSD.\n * @param _amount Amount of OUSD to burn\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\n */\n function redeem(uint256 _amount, uint256 _minimumUnitAmount)\n public\n whenNotCapitalPaused\n nonReentrant\n {\n if (_amount > rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n _redeem(_amount, _minimumUnitAmount);\n }\n\n /**\n * @dev Withdraw a supported asset and burn OUSD.\n * @param _amount Amount of OUSD to burn\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\n */\n function _redeem(uint256 _amount, uint256 _minimumUnitAmount) internal {\n require(_amount > 0, \"Amount must be greater than 0\");\n\n uint256 _totalSupply = oUSD.totalSupply();\n uint256 _backingValue = _totalValue();\n\n if (maxSupplyDiff > 0) {\n // Allow a max difference of maxSupplyDiff% between\n // backing assets value and OUSD total supply\n uint256 diff = _totalSupply.divPrecisely(_backingValue);\n\n require(\n (diff > 1e18 ? diff.sub(1e18) : uint256(1e18).sub(diff)) <=\n maxSupplyDiff,\n \"Backing supply liquidity error\"\n );\n }\n\n emit Redeem(msg.sender, _amount);\n\n // Calculate redemption outputs\n uint256[] memory outputs = _calculateRedeemOutputs(_amount);\n // Send outputs\n for (uint256 i = 0; i < allAssets.length; i++) {\n if (outputs[i] == 0) continue;\n\n IERC20 asset = IERC20(allAssets[i]);\n\n if (asset.balanceOf(address(this)) >= outputs[i]) {\n // Use Vault funds first if sufficient\n asset.safeTransfer(msg.sender, outputs[i]);\n } else {\n address strategyAddr = assetDefaultStrategies[allAssets[i]];\n if (strategyAddr != address(0)) {\n // Nothing in Vault, but something in Strategy, send from there\n IStrategy strategy = IStrategy(strategyAddr);\n strategy.withdraw(msg.sender, allAssets[i], outputs[i]);\n } else {\n // Cant find funds anywhere\n revert(\"Liquidity error\");\n }\n }\n }\n\n if (_minimumUnitAmount > 0) {\n uint256 unitTotal = 0;\n for (uint256 i = 0; i < outputs.length; i++) {\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\n unitTotal = unitTotal.add(\n outputs[i].scaleBy(int8(18 - assetDecimals))\n );\n }\n require(\n unitTotal >= _minimumUnitAmount,\n \"Redeem amount lower than minimum\"\n );\n }\n\n oUSD.burn(msg.sender, _amount);\n\n // Until we can prove that we won't affect the prices of our assets\n // by withdrawing them, this should be here.\n // It's possible that a strategy was off on its asset total, perhaps\n // a reward token sold for more or for less than anticipated.\n if (_amount > rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n }\n\n /**\n * @notice Withdraw a supported asset and burn all OUSD.\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\n */\n function redeemAll(uint256 _minimumUnitAmount)\n external\n whenNotCapitalPaused\n nonReentrant\n {\n // Unfortunately we have to do balanceOf twice, the rebase may change\n // the account balance\n if (oUSD.balanceOf(msg.sender) > rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n _redeem(oUSD.balanceOf(msg.sender), _minimumUnitAmount);\n }\n\n /**\n * @notice Allocate unallocated funds on Vault to strategies.\n * @dev Allocate unallocated funds on Vault to strategies.\n **/\n function allocate() public whenNotCapitalPaused nonReentrant {\n _allocate();\n }\n\n /**\n * @notice Allocate unallocated funds on Vault to strategies.\n * @dev Allocate unallocated funds on Vault to strategies.\n **/\n function _allocate() internal {\n uint256 vaultValue = _totalValueInVault();\n // Nothing in vault to allocate\n if (vaultValue == 0) return;\n uint256 strategiesValue = _totalValueInStrategies();\n // We have a method that does the same as this, gas optimisation\n uint256 calculatedTotalValue = vaultValue.add(strategiesValue);\n\n // We want to maintain a buffer on the Vault so calculate a percentage\n // modifier to multiply each amount being allocated by to enforce the\n // vault buffer\n uint256 vaultBufferModifier;\n if (strategiesValue == 0) {\n // Nothing in Strategies, allocate 100% minus the vault buffer to\n // strategies\n vaultBufferModifier = uint256(1e18).sub(vaultBuffer);\n } else {\n vaultBufferModifier = vaultBuffer.mul(calculatedTotalValue).div(\n vaultValue\n );\n if (1e18 > vaultBufferModifier) {\n // E.g. 1e18 - (1e17 * 10e18)/5e18 = 8e17\n // (5e18 * 8e17) / 1e18 = 4e18 allocated from Vault\n vaultBufferModifier = uint256(1e18).sub(vaultBufferModifier);\n } else {\n // We need to let the buffer fill\n return;\n }\n }\n if (vaultBufferModifier == 0) return;\n\n // Iterate over all assets in the Vault and allocate the the appropriate\n // strategy\n for (uint256 i = 0; i < allAssets.length; i++) {\n IERC20 asset = IERC20(allAssets[i]);\n uint256 assetBalance = asset.balanceOf(address(this));\n // No balance, nothing to do here\n if (assetBalance == 0) continue;\n\n // Multiply the balance by the vault buffer modifier and truncate\n // to the scale of the asset decimals\n uint256 allocateAmount = assetBalance.mulTruncate(\n vaultBufferModifier\n );\n\n address depositStrategyAddr = assetDefaultStrategies[address(\n asset\n )];\n\n if (depositStrategyAddr != address(0) && allocateAmount > 0) {\n IStrategy strategy = IStrategy(depositStrategyAddr);\n // Transfer asset to Strategy and call deposit method to\n // mint or take required action\n asset.safeTransfer(address(strategy), allocateAmount);\n strategy.deposit(address(asset), allocateAmount);\n }\n }\n\n // Harvest for all reward tokens above reward liquidation threshold\n for (uint256 i = 0; i < allStrategies.length; i++) {\n IStrategy strategy = IStrategy(allStrategies[i]);\n address rewardTokenAddress = strategy.rewardTokenAddress();\n if (rewardTokenAddress != address(0)) {\n uint256 liquidationThreshold = strategy\n .rewardLiquidationThreshold();\n if (liquidationThreshold == 0) {\n // No threshold set, always harvest from strategy\n IVault(address(this)).harvest(allStrategies[i]);\n } else {\n // Check balance against liquidation threshold\n // Note some strategies don't hold the reward token balance\n // on their contract so the liquidation threshold should be\n // set to 0\n IERC20 rewardToken = IERC20(rewardTokenAddress);\n uint256 rewardTokenAmount = rewardToken.balanceOf(\n allStrategies[i]\n );\n if (rewardTokenAmount >= liquidationThreshold) {\n IVault(address(this)).harvest(allStrategies[i]);\n }\n }\n }\n }\n\n // Trigger OGN Buyback\n IBuyback(trusteeAddress).swap();\n }\n\n /**\n * @dev Calculate the total value of assets held by the Vault and all\n * strategies and update the supply of OUSD.\n */\n function rebase() public whenNotRebasePaused nonReentrant {\n _rebase();\n }\n\n /**\n * @dev Calculate the total value of assets held by the Vault and all\n * strategies and update the supply of OUSD, optionaly sending a\n * portion of the yield to the trustee.\n */\n function _rebase() internal whenNotRebasePaused {\n uint256 ousdSupply = oUSD.totalSupply();\n if (ousdSupply == 0) {\n return;\n }\n uint256 vaultValue = _totalValue();\n\n // Yield fee collection\n address _trusteeAddress = trusteeAddress; // gas savings\n if (_trusteeAddress != address(0) && (vaultValue > ousdSupply)) {\n uint256 yield = vaultValue.sub(ousdSupply);\n uint256 fee = yield.mul(trusteeFeeBps).div(10000);\n require(yield > fee, \"Fee must not be greater than yield\");\n if (fee > 0) {\n oUSD.mint(_trusteeAddress, fee);\n }\n emit YieldDistribution(_trusteeAddress, yield, fee);\n }\n\n // Only rachet OUSD supply upwards\n ousdSupply = oUSD.totalSupply(); // Final check should use latest value\n if (vaultValue > ousdSupply) {\n oUSD.changeSupply(vaultValue);\n }\n }\n\n /**\n * @dev Determine the total value of assets held by the vault and its\n * strategies.\n * @return uint256 value Total value in USD (1e18)\n */\n function totalValue() external view returns (uint256 value) {\n value = _totalValue();\n }\n\n /**\n * @dev Internal Calculate the total value of the assets held by the\n * vault and its strategies.\n * @return uint256 value Total value in USD (1e18)\n */\n function _totalValue() internal view returns (uint256 value) {\n return _totalValueInVault().add(_totalValueInStrategies());\n }\n\n /**\n * @dev Internal to calculate total value of all assets held in Vault.\n * @return uint256 Total value in ETH (1e18)\n */\n function _totalValueInVault() internal view returns (uint256 value) {\n for (uint256 y = 0; y < allAssets.length; y++) {\n IERC20 asset = IERC20(allAssets[y]);\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\n uint256 balance = asset.balanceOf(address(this));\n if (balance > 0) {\n value = value.add(balance.scaleBy(int8(18 - assetDecimals)));\n }\n }\n }\n\n /**\n * @dev Internal to calculate total value of all assets held in Strategies.\n * @return uint256 Total value in ETH (1e18)\n */\n function _totalValueInStrategies() internal view returns (uint256 value) {\n for (uint256 i = 0; i < allStrategies.length; i++) {\n value = value.add(_totalValueInStrategy(allStrategies[i]));\n }\n }\n\n /**\n * @dev Internal to calculate total value of all assets held by strategy.\n * @param _strategyAddr Address of the strategy\n * @return uint256 Total value in ETH (1e18)\n */\n function _totalValueInStrategy(address _strategyAddr)\n internal\n view\n returns (uint256 value)\n {\n IStrategy strategy = IStrategy(_strategyAddr);\n for (uint256 y = 0; y < allAssets.length; y++) {\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\n if (strategy.supportsAsset(allAssets[y])) {\n uint256 balance = strategy.checkBalance(allAssets[y]);\n if (balance > 0) {\n value = value.add(\n balance.scaleBy(int8(18 - assetDecimals))\n );\n }\n }\n }\n }\n\n /**\n * @notice Get the balance of an asset held in Vault and all strategies.\n * @param _asset Address of asset\n * @return uint256 Balance of asset in decimals of asset\n */\n function checkBalance(address _asset) external view returns (uint256) {\n return _checkBalance(_asset);\n }\n\n /**\n * @notice Get the balance of an asset held in Vault and all strategies.\n * @param _asset Address of asset\n * @return uint256 Balance of asset in decimals of asset\n */\n function _checkBalance(address _asset)\n internal\n view\n returns (uint256 balance)\n {\n IERC20 asset = IERC20(_asset);\n balance = asset.balanceOf(address(this));\n for (uint256 i = 0; i < allStrategies.length; i++) {\n IStrategy strategy = IStrategy(allStrategies[i]);\n if (strategy.supportsAsset(_asset)) {\n balance = balance.add(strategy.checkBalance(_asset));\n }\n }\n }\n\n /**\n * @notice Get the balance of all assets held in Vault and all strategies.\n * @return uint256 Balance of all assets (1e18)\n */\n function _checkBalance() internal view returns (uint256 balance) {\n for (uint256 i = 0; i < allAssets.length; i++) {\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\n balance = balance.add(\n _checkBalance(allAssets[i]).scaleBy(int8(18 - assetDecimals))\n );\n }\n }\n\n /**\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\n * coins that will be returned\n */\n function calculateRedeemOutputs(uint256 _amount)\n external\n view\n returns (uint256[] memory)\n {\n return _calculateRedeemOutputs(_amount);\n }\n\n /**\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\n * coins that will be returned.\n * @return Array of amounts respective to the supported assets\n */\n function _calculateRedeemOutputs(uint256 _amount)\n internal\n view\n returns (uint256[] memory outputs)\n {\n // We always give out coins in proportion to how many we have,\n // Now if all coins were the same value, this math would easy,\n // just take the percentage of each coin, and multiply by the\n // value to be given out. But if coins are worth more than $1,\n // then we would end up handing out too many coins. We need to\n // adjust by the total value of coins.\n //\n // To do this, we total up the value of our coins, by their\n // percentages. Then divide what we would otherwise give out by\n // this number.\n //\n // Let say we have 100 DAI at $1.06 and 200 USDT at $1.00.\n // So for every 1 DAI we give out, we'll be handing out 2 USDT\n // Our total output ratio is: 33% * 1.06 + 66% * 1.00 = 1.02\n //\n // So when calculating the output, we take the percentage of\n // each coin, times the desired output value, divided by the\n // totalOutputRatio.\n //\n // For example, withdrawing: 30 OUSD:\n // DAI 33% * 30 / 1.02 = 9.80 DAI\n // USDT = 66 % * 30 / 1.02 = 19.60 USDT\n //\n // Checking these numbers:\n // 9.80 DAI * 1.06 = $10.40\n // 19.60 USDT * 1.00 = $19.60\n //\n // And so the user gets $10.40 + $19.60 = $30 worth of value.\n\n uint256 assetCount = getAssetCount();\n uint256[] memory assetPrices = _getAssetPrices(true);\n uint256[] memory assetBalances = new uint256[](assetCount);\n uint256[] memory assetDecimals = new uint256[](assetCount);\n uint256 totalBalance = 0;\n uint256 totalOutputRatio = 0;\n outputs = new uint256[](assetCount);\n\n // Calculate redeem fee\n if (redeemFeeBps > 0) {\n uint256 redeemFee = _amount.mul(redeemFeeBps).div(10000);\n _amount = _amount.sub(redeemFee);\n }\n\n // Calculate assets balances and decimals once,\n // for a large gas savings.\n for (uint256 i = 0; i < allAssets.length; i++) {\n uint256 balance = _checkBalance(allAssets[i]);\n uint256 decimals = Helpers.getDecimals(allAssets[i]);\n assetBalances[i] = balance;\n assetDecimals[i] = decimals;\n totalBalance = totalBalance.add(\n balance.scaleBy(int8(18 - decimals))\n );\n }\n // Calculate totalOutputRatio\n for (uint256 i = 0; i < allAssets.length; i++) {\n uint256 price = assetPrices[i];\n // Never give out more than one\n // stablecoin per dollar of OUSD\n if (price < 1e18) {\n price = 1e18;\n }\n uint256 ratio = assetBalances[i]\n .scaleBy(int8(18 - assetDecimals[i]))\n .mul(price)\n .div(totalBalance);\n totalOutputRatio = totalOutputRatio.add(ratio);\n }\n // Calculate final outputs\n uint256 factor = _amount.divPrecisely(totalOutputRatio);\n for (uint256 i = 0; i < allAssets.length; i++) {\n outputs[i] = assetBalances[i].mul(factor).div(totalBalance);\n }\n }\n\n /**\n * @notice Get an array of the supported asset prices in USD.\n * @return uint256[] Array of asset prices in USD (1e18)\n */\n function _getAssetPrices(bool useMax)\n internal\n view\n returns (uint256[] memory assetPrices)\n {\n assetPrices = new uint256[](getAssetCount());\n\n IOracle oracle = IOracle(priceProvider);\n // Price from Oracle is returned with 8 decimals\n // _amount is in assetDecimals\n for (uint256 i = 0; i < allAssets.length; i++) {\n assetPrices[i] = oracle.price(allAssets[i]).scaleBy(int8(18 - 8));\n }\n }\n\n /***************************************\n Utils\n ****************************************/\n\n /**\n * @dev Return the number of assets suppported by the Vault.\n */\n function getAssetCount() public view returns (uint256) {\n return allAssets.length;\n }\n\n /**\n * @dev Return all asset addresses in order\n */\n function getAllAssets() external view returns (address[] memory) {\n return allAssets;\n }\n\n /**\n * @dev Return the number of strategies active on the Vault.\n */\n function getStrategyCount() external view returns (uint256) {\n return allStrategies.length;\n }\n\n function isSupportedAsset(address _asset) external view returns (bool) {\n return assets[_asset].isSupported;\n }\n\n /**\n * @dev Falldown to the admin implementation\n * @notice This is a catch all for all functions not declared in core\n */\n function() external payable {\n bytes32 slot = adminImplPosition;\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize)\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas, sload(slot), 0, calldatasize, 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize)\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize)\n }\n default {\n return(0, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/interfaces/IVault.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IVault {\n event AssetSupported(address _asset);\n event StrategyApproved(address _addr);\n event StrategyRemoved(address _addr);\n event Mint(address _addr, uint256 _value);\n event Redeem(address _addr, uint256 _value);\n event DepositsPaused();\n event DepositsUnpaused();\n\n // Governable.sol\n function transferGovernance(address _newGovernor) external;\n\n function claimGovernance() external;\n\n function governor() external view returns (address);\n\n // VaultAdmin.sol\n function setPriceProvider(address _priceProvider) external;\n\n function priceProvider() external view returns (address);\n\n function setRedeemFeeBps(uint256 _redeemFeeBps) external;\n\n function redeemFeeBps() external view returns (uint256);\n\n function setVaultBuffer(uint256 _vaultBuffer) external;\n\n function vaultBuffer() external view returns (uint256);\n\n function setAutoAllocateThreshold(uint256 _threshold) external;\n\n function autoAllocateThreshold() external view returns (uint256);\n\n function setRebaseThreshold(uint256 _threshold) external;\n\n function rebaseThreshold() external view returns (uint256);\n\n function setStrategistAddr(address _address) external;\n\n function strategistAddr() external view returns (address);\n\n function setUniswapAddr(address _address) external;\n\n function uniswapAddr() external view returns (address);\n\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;\n\n function maxSupplyDiff() external view returns (uint256);\n\n function setTrusteeAddress(address _address) external;\n\n function trusteeAddress() external view returns (address);\n\n function setTrusteeFeeBps(uint256 _basis) external;\n\n function trusteeFeeBps() external view returns (uint256);\n\n function supportAsset(address _asset) external;\n\n function approveStrategy(address _addr) external;\n\n function removeStrategy(address _addr) external;\n\n function setAssetDefaultStrategy(address _asset, address _strategy)\n external;\n\n function assetDefaultStrategies(address _asset)\n external\n view\n returns (address);\n\n function pauseRebase() external;\n\n function unpauseRebase() external;\n\n function rebasePaused() external view returns (bool);\n\n function pauseCapital() external;\n\n function unpauseCapital() external;\n\n function capitalPaused() external view returns (bool);\n\n function transferToken(address _asset, uint256 _amount) external;\n\n function harvest() external;\n\n function harvest(address _strategyAddr) external;\n\n function priceUSDMint(address asset) external view returns (uint256);\n\n function priceUSDRedeem(address asset) external view returns (uint256);\n\n function withdrawAllFromStrategy(address _strategyAddr) external;\n\n function withdrawAllFromStrategies() external;\n\n // VaultCore.sol\n function mint(\n address _asset,\n uint256 _amount,\n uint256 _minimumOusdAmount\n ) external;\n\n function mintMultiple(\n address[] calldata _assets,\n uint256[] calldata _amount,\n uint256 _minimumOusdAmount\n ) external;\n\n function redeem(uint256 _amount, uint256 _minimumUnitAmount) external;\n\n function redeemAll(uint256 _minimumUnitAmount) external;\n\n function allocate() external;\n\n function reallocate(\n address _strategyFromAddress,\n address _strategyToAddress,\n address[] calldata _assets,\n uint256[] calldata _amounts\n ) external;\n\n function rebase() external;\n\n function totalValue() external view returns (uint256 value);\n\n function checkBalance() external view returns (uint256);\n\n function checkBalance(address _asset) external view returns (uint256);\n\n function calculateRedeemOutputs(uint256 _amount)\n external\n view\n returns (uint256[] memory);\n\n function getAssetCount() external view returns (uint256);\n\n function getAllAssets() external view returns (address[] memory);\n\n function getStrategyCount() external view returns (uint256);\n\n function isSupportedAsset(address _asset) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IBuyback.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IBuyback {\n function swap() external;\n}\n" + }, + "contracts/mocks/MockRebornMinter.sol": { + "content": "pragma solidity ^0.5.11;\n\nimport { IVault } from \"../interfaces/IVault.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"hardhat/console.sol\";\n\ncontract Sanctum {\n address public asset;\n address public vault;\n address public reborner;\n bool public shouldAttack = false;\n uint256 public targetMethod;\n address public ousdContract;\n\n constructor(address _asset, address _vault) public {\n asset = _asset;\n vault = _vault;\n }\n\n function deploy(uint256 salt, bytes memory bytecode)\n public\n returns (address addr)\n {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n }\n\n function computeAddress(uint256 salt, bytes memory bytecode)\n public\n view\n returns (address)\n {\n bytes32 bytecodeHashHash = keccak256(bytecode);\n bytes32 _data = keccak256(\n abi.encodePacked(\n bytes1(0xff),\n address(this),\n salt,\n bytecodeHashHash\n )\n );\n return address(bytes20(_data << 96));\n }\n\n function setShouldAttack(bool _shouldAttack) public {\n shouldAttack = _shouldAttack;\n }\n\n function setTargetMethod(uint256 target) public {\n targetMethod = target;\n }\n\n function setOUSDAddress(address _ousdContract) public {\n ousdContract = _ousdContract;\n }\n}\n\ncontract Reborner {\n Sanctum sanctum;\n bool logging = false;\n\n constructor(address _sanctum) public {\n log(\"We are created...\");\n sanctum = Sanctum(_sanctum);\n if (sanctum.shouldAttack()) {\n log(\"We are attacking now...\");\n\n uint256 target = sanctum.targetMethod();\n\n if (target == 1) {\n redeem();\n } else if (target == 2) {\n transfer();\n } else {\n mint();\n }\n }\n }\n\n function mint() public {\n log(\"We are attempting to mint..\");\n address asset = sanctum.asset();\n address vault = sanctum.vault();\n IERC20(asset).approve(vault, 1e18);\n IVault(vault).mint(asset, 1e18, 0);\n log(\"We are now minting..\");\n }\n\n function redeem() public {\n log(\"We are attempting to redeem..\");\n address vault = sanctum.vault();\n IVault(vault).redeem(1e18, 1e18);\n log(\"We are now redeeming..\");\n }\n\n function transfer() public {\n log(\"We are attempting to transfer..\");\n address ousd = sanctum.ousdContract();\n require(IERC20(ousd).transfer(address(1), 1e18), \"transfer failed\");\n log(\"We are now transfering..\");\n }\n\n function bye() public {\n log(\"We are now destructing..\");\n selfdestruct(msg.sender);\n }\n\n function log(string memory message) internal {\n if (logging) {\n console.log(message);\n }\n }\n}\n" + }, + "hardhat/console.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >= 0.4.22 <0.8.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 logByte(byte p0) internal view {\n\t\t_sendLogPayload(abi.encodeWithSignature(\"log(byte)\", 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/mocks/MockNonRebasing.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IVault } from \"../interfaces/IVault.sol\";\n\nimport { OUSD } from \"../token/OUSD.sol\";\n\ncontract MockNonRebasing {\n OUSD oUSD;\n\n function setOUSD(address _oUSDAddress) public {\n oUSD = OUSD(_oUSDAddress);\n }\n\n function rebaseOptIn() public {\n oUSD.rebaseOptIn();\n }\n\n function rebaseOptOut() public {\n oUSD.rebaseOptOut();\n }\n\n function transfer(address _to, uint256 _value) public {\n oUSD.transfer(_to, _value);\n }\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) public {\n oUSD.transferFrom(_from, _to, _value);\n }\n\n function increaseAllowance(address _spender, uint256 _addedValue) public {\n oUSD.increaseAllowance(_spender, _addedValue);\n }\n\n function mintOusd(\n address _vaultContract,\n address _asset,\n uint256 _amount\n ) public {\n IVault(_vaultContract).mint(_asset, _amount, 0);\n }\n\n function redeemOusd(address _vaultContract, uint256 _amount) public {\n IVault(_vaultContract).redeem(_amount, 0);\n }\n\n function approveFor(\n address _contract,\n address _spender,\n uint256 _addedValue\n ) public {\n IERC20(_contract).approve(_spender, _addedValue);\n }\n}\n" + }, + "contracts/flipper/FlipperDev.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../governance/Governable.sol\";\nimport \"../token/OUSD.sol\";\nimport \"../interfaces/Tether.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n// Contract to exchange usdt, usdc, dai from and to ousd.\n// - 1 to 1. No slippage\n// - Optimized for low gas usage\n// - No guarantee of availability\n\ncontract FlipperDev is Governable {\n using SafeERC20 for IERC20;\n\n uint256 constant MAXIMUM_PER_TRADE = (25000 * 1e18);\n\n // Settable coin addresses allow easy testing and use of mock currencies.\n IERC20 dai = IERC20(0);\n OUSD ousd = OUSD(0);\n IERC20 usdc = IERC20(0);\n Tether usdt = Tether(0);\n\n // ---------------------\n // Dev constructor\n // ---------------------\n constructor(\n address dai_,\n address ousd_,\n address usdc_,\n address usdt_\n ) public {\n dai = IERC20(dai_);\n ousd = OUSD(ousd_);\n usdc = IERC20(usdc_);\n usdt = Tether(usdt_);\n require(address(ousd) != address(0));\n require(address(dai) != address(0));\n require(address(usdc) != address(0));\n require(address(usdt) != address(0));\n }\n\n // -----------------\n // Trading functions\n // -----------------\n\n /// @notice Purchase OUSD with Dai\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithDai(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(dai.transferFrom(msg.sender, address(this), amount));\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for Dai\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForDai(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(dai.transfer(msg.sender, amount));\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n /// @notice Purchase OUSD with USDC\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithUsdc(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // Potential rounding error is an intentional tradeoff\n require(usdc.transferFrom(msg.sender, address(this), amount / 1e12));\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for USDC\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForUsdc(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(usdc.transfer(msg.sender, amount / 1e12));\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n /// @notice Purchase OUSD with USDT\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithUsdt(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // Potential rounding error is an intentional tradeoff\n // USDT does not return a boolean and reverts,\n // so no need for a require.\n usdt.transferFrom(msg.sender, address(this), amount / 1e12);\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for USDT\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForUsdt(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // USDT does not return a boolean and reverts,\n // so no need for a require.\n usdt.transfer(msg.sender, amount / 1e12);\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n // --------------------\n // Governance functions\n // --------------------\n\n /// @dev Opting into yield reduces the gas cost per transfer by about 4K, since\n /// ousd needs to do less accounting and one less storage write.\n function rebaseOptIn() external onlyGovernor nonReentrant {\n ousd.rebaseOptIn();\n }\n\n /// @notice Owner function to withdraw a specific amount of a token\n function withdraw(address token, uint256 amount)\n external\n onlyGovernor\n nonReentrant\n {\n IERC20(token).safeTransfer(_governor(), amount);\n }\n\n /// @notice Owner function to withdraw all tradable tokens\n /// @dev Equivalent to \"pausing\" the contract.\n function withdrawAll() external onlyGovernor nonReentrant {\n IERC20(dai).safeTransfer(_governor(), dai.balanceOf(address(this)));\n IERC20(ousd).safeTransfer(_governor(), ousd.balanceOf(address(this)));\n IERC20(address(usdt)).safeTransfer(\n _governor(),\n usdt.balanceOf(address(this))\n );\n IERC20(usdc).safeTransfer(_governor(), usdc.balanceOf(address(this)));\n }\n}\n" + }, + "contracts/interfaces/Tether.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface Tether {\n function transfer(address to, uint256 value) external;\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n ) external;\n\n function balanceOf(address) external returns (uint256);\n}\n" + }, + "contracts/flipper/Flipper.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../governance/Governable.sol\";\nimport \"../token/OUSD.sol\";\nimport \"../interfaces/Tether.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n// Contract to exchange usdt, usdc, dai from and to ousd.\n// - 1 to 1. No slippage\n// - Optimized for low gas usage\n// - No guarantee of availability\n\ncontract Flipper is Governable {\n using SafeERC20 for IERC20;\n\n uint256 constant MAXIMUM_PER_TRADE = (25000 * 1e18);\n\n // Saves approx 4K gas per swap by using hardcoded addresses.\n IERC20 dai = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);\n OUSD constant ousd = OUSD(0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86);\n IERC20 usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n Tether constant usdt = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n // -----------\n // Constructor\n // -----------\n constructor() public {}\n\n // -----------------\n // Trading functions\n // -----------------\n\n /// @notice Purchase OUSD with Dai\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithDai(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(dai.transferFrom(msg.sender, address(this), amount));\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for Dai\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForDai(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(dai.transfer(msg.sender, amount));\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n /// @notice Purchase OUSD with USDC\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithUsdc(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // Potential rounding error is an intentional tradeoff\n require(usdc.transferFrom(msg.sender, address(this), amount / 1e12));\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for USDC\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForUsdc(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(usdc.transfer(msg.sender, amount / 1e12));\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n /// @notice Purchase OUSD with USDT\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithUsdt(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // Potential rounding error is an intentional tradeoff\n // USDT does not return a boolean and reverts,\n // so no need for a require.\n usdt.transferFrom(msg.sender, address(this), amount / 1e12);\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for USDT\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForUsdt(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // USDT does not return a boolean and reverts,\n // so no need for a require.\n usdt.transfer(msg.sender, amount / 1e12);\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n // --------------------\n // Governance functions\n // --------------------\n\n /// @dev Opting into yield reduces the gas cost per transfer by about 4K, since\n /// ousd needs to do less accounting and one less storage write.\n function rebaseOptIn() external onlyGovernor nonReentrant {\n ousd.rebaseOptIn();\n }\n\n /// @notice Owner function to withdraw a specific amount of a token\n function withdraw(address token, uint256 amount)\n external\n onlyGovernor\n nonReentrant\n {\n IERC20(token).safeTransfer(_governor(), amount);\n }\n\n /// @notice Owner function to withdraw all tradable tokens\n /// @dev Equivalent to \"pausing\" the contract.\n function withdrawAll() external onlyGovernor nonReentrant {\n IERC20(dai).safeTransfer(_governor(), dai.balanceOf(address(this)));\n IERC20(ousd).safeTransfer(_governor(), ousd.balanceOf(address(this)));\n IERC20(address(usdt)).safeTransfer(\n _governor(),\n usdt.balanceOf(address(this))\n );\n IERC20(usdc).safeTransfer(_governor(), usdc.balanceOf(address(this)));\n }\n}\n" + }, + "contracts/liquidity/LiquidityReward.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\n//\n// LiquidityReward contract doles out reward for liquidity\n// base off of Sushiswap's MasterChef: https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol\n//\ncontract LiquidityReward is Initializable, Governable {\n using SafeMath for uint256;\n using StableMath for uint256;\n using SafeERC20 for IERC20;\n\n // Info of each user.\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n int256 rewardDebt; // Reward debt. See explanation below.\n //\n // We do some fancy math here. Basically, any point in time, the amount of Reward Tokens\n // entitled to a user but is pending to be distributed is:\n //\n // pending reward = (user.amount * pool.accRewardPerShare) - user.rewardDebt\n //\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\n // 1. The pool's `accRewardPerShare` (and `lastRewardBlock`) 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` gets updated.\n //\n // NOTE: rewardDebt can go negative because we allow withdraws without claiming the reward\n // in that case we owe the account holder some reward.\n }\n\n // Info of each pool.\n struct PoolInfo {\n IERC20 lpToken; // Address of LP token contract.\n uint256 lastRewardBlock; // Last block number that Reward calculation occurs.\n uint256 accRewardPerShare; // Accumulated Reward per share in reward precision. See below.\n }\n\n // The Reward token\n IERC20 public reward;\n\n // Reward tokens created per block in 1e18 precision.\n uint256 public rewardPerBlock;\n\n // Info on the LP.\n PoolInfo public pool;\n // total Reward debt, useful to calculate if we have enough to pay out all rewards\n int256 public totalRewardDebt;\n // Info of each user that stakes LP tokens.\n mapping(address => UserInfo) public userInfo;\n // The block number when Liquidity rewards ends.\n uint256 public endBlock;\n\n event CampaignStarted(\n uint256 rewardRate,\n uint256 startBlock,\n uint256 endBlock\n );\n event CampaignStopped(uint256 endBlock);\n event Deposit(address indexed user, uint256 amount);\n event Withdraw(address indexed user, uint256 amount);\n event Claim(address indexed user, uint256 amount);\n\n /**\n * Initializer for setting up Liquidity Reward internal state.\n * @param _reward Address of the reward token(OGN)\n * @param _lpToken Address of the LP token(Uniswap Pair)\n */\n function initialize(IERC20 _reward, IERC20 _lpToken)\n external\n onlyGovernor\n initializer\n {\n reward = _reward;\n pool.lpToken = _lpToken;\n pool.lastRewardBlock = block.number;\n }\n\n /**\n * @dev start a new reward campaign.\n * This will calculate all rewards up to the current block at the old rate.\n * This ensures that we pay everyone at the promised rate before update to the new rate.\n * @param _rewardPerBlock Amount rewarded per block\n * @param _startBlock Block number that we want to start the rewards at (0 for current block)\n * @param _numBlocks number of blocks that the campaign should last\n */\n function startCampaign(\n uint256 _rewardPerBlock,\n uint256 _startBlock,\n uint256 _numBlocks\n ) external onlyGovernor {\n // Calculate up to the current block at the current rate for everyone.\n updatePool();\n\n // total Pending calculated at the current pool rate\n uint256 totalPending = subDebt(\n pool.accRewardPerShare.mulTruncate(\n pool.lpToken.balanceOf(address(this))\n ),\n totalRewardDebt\n );\n\n require(\n reward.balanceOf(address(this)) >=\n _rewardPerBlock.mul(_numBlocks).add(totalPending),\n \"startCampaign: insufficient rewards\"\n );\n\n uint256 startBlock = _startBlock;\n if (startBlock == 0) {\n // start block number isn't given so we start at the current\n startBlock = block.number;\n }\n require(\n startBlock >= block.number,\n \"startCampaign: _startBlock can't be in the past\"\n );\n endBlock = startBlock.add(_numBlocks);\n // we don't start accrue until the startBlock\n pool.lastRewardBlock = startBlock;\n // new blocks start at the new reward rate\n rewardPerBlock = _rewardPerBlock;\n emit CampaignStarted(rewardPerBlock, startBlock, endBlock);\n }\n\n function stopCampaign() external onlyGovernor {\n //calculate until current pool\n updatePool();\n //end the block here (the CampaignMultiplier will be zero)\n endBlock = block.number;\n emit CampaignStopped(endBlock);\n }\n\n function campaignActive() external view returns (bool) {\n return endBlock > block.number && block.number >= pool.lastRewardBlock;\n }\n\n function balanceOf(address _account) external view returns (uint256) {\n return userInfo[_account].amount;\n }\n\n /**\n * @dev calculate the number of blocks since we last updated\n * within start and end as constraints\n * @param _to Block number of the ending point.\n * @return multiplier Multiplier over the given _from to _to block.\n */\n function getCampaignMultiplier(uint256 _to)\n internal\n view\n returns (uint256)\n {\n uint256 from = pool.lastRewardBlock;\n if (from > endBlock) {\n return 0;\n } else {\n return (_to < endBlock ? _to : endBlock).sub(from);\n }\n }\n\n /**\n * @dev View function to see pending rewards for each account on frontend.\n * @param _user Address of the account we're looking up.\n * @return reward Total rewards owed to this account.\n */\n function pendingRewards(address _user) external view returns (uint256) {\n UserInfo storage user = userInfo[_user];\n return _pendingRewards(user);\n }\n\n function _pendingRewards(UserInfo storage user)\n internal\n view\n returns (uint256)\n {\n uint256 accRewardPerShare = pool.accRewardPerShare;\n if (block.number > pool.lastRewardBlock) {\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\n if (lpSupply != 0) {\n uint256 multiplier = getCampaignMultiplier(block.number);\n uint256 incReward = multiplier.mul(rewardPerBlock);\n accRewardPerShare = accRewardPerShare.add(\n incReward.divPrecisely(lpSupply)\n );\n }\n }\n return\n subDebt(\n user.amount.mulTruncate(accRewardPerShare),\n user.rewardDebt\n );\n }\n\n /**\n * @dev View function to see total outstanding rewards for the entire contract.\n * This is how much is owed when everyone pulls out.\n * @return reward Total rewards owed to everyone.\n */\n function totalOutstandingRewards() external view returns (uint256) {\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n uint256 multiplier = getCampaignMultiplier(block.number);\n uint256 incReward = multiplier.mul(rewardPerBlock);\n uint256 accRewardPerShare = pool.accRewardPerShare;\n accRewardPerShare = accRewardPerShare.add(\n incReward.divPrecisely(lpSupply)\n );\n return\n subDebt(\n accRewardPerShare.mulTruncate(lpSupply),\n totalRewardDebt\n );\n }\n // no supply or not even started\n return 0;\n }\n\n /**\n * @dev External call for updating the pool.\n */\n function doUpdatePool() external {\n // There should be no harm allowing anyone to call this function.\n // It just updates the latest accRewardPerShare for the pool.\n updatePool();\n }\n\n /**\n * @dev Update the Liquidity Pool reward multiplier.\n * This locks in the accRewardPerShare from the last update block number to now.\n * Will fail if we do not have enough to pay everyone.\n * Always call updatePool whenever the balance changes!\n */\n function updatePool() internal {\n if (\n block.number <= pool.lastRewardBlock ||\n endBlock <= pool.lastRewardBlock\n ) {\n return;\n }\n\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\n if (lpSupply == 0) {\n pool.lastRewardBlock = block.number;\n return;\n }\n\n uint256 incReward = getCampaignMultiplier(block.number).mul(\n rewardPerBlock\n );\n // we are of course assuming lpTokens are in 1e18 precision\n uint256 accRewardPerShare = pool.accRewardPerShare.add(\n incReward.divPrecisely(lpSupply)\n );\n\n pool.accRewardPerShare = accRewardPerShare;\n pool.lastRewardBlock = block.number;\n }\n\n /**\n * @dev Deposit LP tokens into contract, must be preapproved.\n * @param _amount Amount of LPToken to deposit.\n */\n function deposit(uint256 _amount) external {\n UserInfo storage user = userInfo[msg.sender];\n updatePool();\n if (_amount > 0) {\n user.amount = user.amount.add(_amount);\n // newDebt is equal to the change in amount * accRewardPerShare (note accRewardPerShare is historic)\n int256 newDebt = int256(\n _amount.mulTruncate(pool.accRewardPerShare)\n );\n user.rewardDebt += newDebt;\n totalRewardDebt += newDebt;\n emit Deposit(msg.sender, _amount);\n pool.lpToken.safeTransferFrom(\n address(msg.sender),\n address(this),\n _amount\n );\n }\n }\n\n /**\n * @dev Exit out of the contract completely, withdraw LP tokens and claim rewards\n */\n function exit() external {\n UserInfo storage user = userInfo[msg.sender];\n // withdraw everything\n _withdraw(user, user.amount, true);\n }\n\n /**\n * @dev Withdraw LP tokens from contract.\n * @param _amount Amount of LPToken to withdraw.\n * @param _claim Boolean do we want to claim our rewards or not\n */\n function withdraw(uint256 _amount, bool _claim) external {\n UserInfo storage user = userInfo[msg.sender];\n _withdraw(user, _amount, _claim);\n }\n\n function _withdraw(\n UserInfo storage user,\n uint256 _amount,\n bool _claim\n ) internal {\n require(user.amount >= _amount, \"withdraw: overflow\");\n updatePool();\n\n // newDebt is equal to the change in amount * accRewardPerShare (note accRewardPerShare is historic)\n int256 newDebt = -int256(_amount.mulTruncate(pool.accRewardPerShare));\n if (_claim) {\n //This is an optimization so we don't modify the storage variable twice\n uint256 pending = subDebt(\n user.amount.mulTruncate(pool.accRewardPerShare),\n user.rewardDebt\n );\n if (pending > 0) {\n reward.safeTransfer(msg.sender, pending);\n emit Claim(msg.sender, pending);\n }\n newDebt += int256(pending);\n }\n\n // actually make the changes to the amount and debt\n if (_amount > 0) {\n user.amount = user.amount.sub(_amount);\n pool.lpToken.safeTransfer(address(msg.sender), _amount);\n }\n user.rewardDebt += newDebt;\n totalRewardDebt += newDebt;\n emit Withdraw(msg.sender, _amount);\n }\n\n /**\n * @dev Claim all pending rewards up to current block\n */\n function claim() external {\n UserInfo storage user = userInfo[msg.sender];\n uint256 pending = _pendingRewards(user);\n if (pending > 0) {\n emit Claim(msg.sender, pending);\n int256 debtDelta = int256(pending);\n user.rewardDebt += debtDelta;\n totalRewardDebt += debtDelta;\n reward.safeTransfer(msg.sender, pending);\n }\n }\n\n function subDebt(uint256 amount, int256 debt)\n internal\n pure\n returns (uint256 result)\n {\n if (debt < 0) {\n result = amount.add(uint256(-debt));\n } else {\n result = amount.sub(uint256(debt));\n }\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.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 {ERC20Mintable}.\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 guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 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 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20};\n *\n * Requirements:\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for `sender`'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\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 returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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 returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(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 {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.\n *\n * This is 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(address owner, address spender, uint256 amount) internal {\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 Destroys `amount` tokens from `account`.`amount` is then deducted\n * from the caller's allowance.\n *\n * See {_burn} and {_approve}.\n */\n function _burnFrom(address account, uint256 amount) internal {\n _burn(account, amount);\n _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, \"ERC20: burn amount exceeds allowance\"));\n }\n}\n" + }, + "@openzeppelin/contracts/GSN/Context.sol": { + "content": "pragma solidity ^0.5.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 GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\ncontract Context {\n // Empty internal constructor, to prevent people from mistakenly deploying\n // an instance of this contract, which should be used via inheritance.\n constructor () internal { }\n // solhint-disable-previous-line no-empty-blocks\n\n function _msgSender() internal view returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./ERC20.sol\";\nimport \"../../lifecycle/Pausable.sol\";\n\n/**\n * @title Pausable token\n * @dev ERC20 with pausable transfers and allowances.\n *\n * Useful if you want to stop trades until the end of a crowdsale, or have\n * an emergency switch for freezing all token transfers in the event of a large\n * bug.\n */\ncontract ERC20Pausable is ERC20, Pausable {\n function transfer(address to, uint256 value) public whenNotPaused returns (bool) {\n return super.transfer(to, value);\n }\n\n function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) {\n return super.transferFrom(from, to, value);\n }\n\n function approve(address spender, uint256 value) public whenNotPaused returns (bool) {\n return super.approve(spender, value);\n }\n\n function increaseAllowance(address spender, uint256 addedValue) public whenNotPaused returns (bool) {\n return super.increaseAllowance(spender, addedValue);\n }\n\n function decreaseAllowance(address spender, uint256 subtractedValue) public whenNotPaused returns (bool) {\n return super.decreaseAllowance(spender, subtractedValue);\n }\n}\n" + }, + "@openzeppelin/contracts/lifecycle/Pausable.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../GSN/Context.sol\";\nimport \"../access/roles/PauserRole.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\ncontract Pausable is Context, PauserRole {\n /**\n * @dev Emitted when the pause is triggered by a pauser (`account`).\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by a pauser (`account`).\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state. Assigns the Pauser role\n * to the deployer.\n */\n constructor () internal {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n */\n modifier whenNotPaused() {\n require(!_paused, \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n */\n modifier whenPaused() {\n require(_paused, \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Called by a pauser to pause, triggers stopped state.\n */\n function pause() public onlyPauser whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Called by a pauser to unpause, returns to normal state.\n */\n function unpause() public onlyPauser whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/access/roles/PauserRole.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"../Roles.sol\";\n\ncontract PauserRole is Context {\n using Roles for Roles.Role;\n\n event PauserAdded(address indexed account);\n event PauserRemoved(address indexed account);\n\n Roles.Role private _pausers;\n\n constructor () internal {\n _addPauser(_msgSender());\n }\n\n modifier onlyPauser() {\n require(isPauser(_msgSender()), \"PauserRole: caller does not have the Pauser role\");\n _;\n }\n\n function isPauser(address account) public view returns (bool) {\n return _pausers.has(account);\n }\n\n function addPauser(address account) public onlyPauser {\n _addPauser(account);\n }\n\n function renouncePauser() public {\n _removePauser(_msgSender());\n }\n\n function _addPauser(address account) internal {\n _pausers.add(account);\n emit PauserAdded(account);\n }\n\n function _removePauser(address account) internal {\n _pausers.remove(account);\n emit PauserRemoved(account);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Roles.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @title Roles\n * @dev Library for managing addresses assigned to a Role.\n */\nlibrary Roles {\n struct Role {\n mapping (address => bool) bearer;\n }\n\n /**\n * @dev Give an account access to this role.\n */\n function add(Role storage role, address account) internal {\n require(!has(role, account), \"Roles: account already has role\");\n role.bearer[account] = true;\n }\n\n /**\n * @dev Remove an account's access to this role.\n */\n function remove(Role storage role, address account) internal {\n require(has(role, account), \"Roles: account does not have role\");\n role.bearer[account] = false;\n }\n\n /**\n * @dev Check if an account has this role.\n * @return bool\n */\n function has(Role storage role, address account) internal view returns (bool) {\n require(account != address(0), \"Roles: account is the zero address\");\n return role.bearer[account];\n }\n}\n" + }, + "@openzeppelin/contracts/access/roles/MinterRole.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"../Roles.sol\";\n\ncontract MinterRole is Context {\n using Roles for Roles.Role;\n\n event MinterAdded(address indexed account);\n event MinterRemoved(address indexed account);\n\n Roles.Role private _minters;\n\n constructor () internal {\n _addMinter(_msgSender());\n }\n\n modifier onlyMinter() {\n require(isMinter(_msgSender()), \"MinterRole: caller does not have the Minter role\");\n _;\n }\n\n function isMinter(address account) public view returns (bool) {\n return _minters.has(account);\n }\n\n function addMinter(address account) public onlyMinter {\n _addMinter(account);\n }\n\n function renounceMinter() public {\n _removeMinter(_msgSender());\n }\n\n function _addMinter(address account) internal {\n _minters.add(account);\n emit MinterAdded(account);\n }\n\n function _removeMinter(address account) internal {\n _minters.remove(account);\n emit MinterRemoved(account);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\ncontract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev See {ERC20-_burnFrom}.\n */\n function burnFrom(address account, uint256 amount) public {\n _burnFrom(account, amount);\n }\n}\n" + }, + "contracts/mocks/MockOGN.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\";\n\nimport \"./WhitelistedPausableToken.sol\";\n\n/**\n * @title Origin token (OGN).\n *\n * @dev Token that allows minting, burning, and pausing by contract owner.\n * @dev Important note:\n * @dev There is a known race condition in the ERC20 standard on the approve() method.\n * @dev See details: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n * @dev The Origin token contract implements the increaseApproval() and decreaseApproval() methods.\n * @dev It is strongly recommended to use those methods rather than approve()\n * @dev when updating the token allowance.\n */\n// Removed ERC20Mintable since this is a Mock and we're just exposing the mint function directly\ncontract MockOGN is ERC20Burnable, WhitelistedPausableToken, ERC20Detailed {\n event AddCallSpenderWhitelist(address enabler, address spender);\n event RemoveCallSpenderWhitelist(address disabler, address spender);\n\n mapping(address => bool) public callSpenderWhitelist;\n\n // @dev Constructor that gives msg.sender all initial tokens.\n constructor(uint256 _initialSupply)\n public\n ERC20Detailed(\"OriginToken\", \"OGN\", 18)\n {\n owner = msg.sender;\n _mint(owner, _initialSupply);\n }\n\n // @dev Helper method for mocks testing to allow tests to quickly fund users\n // @param _value Amount of token to be created\n function mint(uint256 _value) external returns (bool) {\n _mint(msg.sender, _value);\n return true;\n }\n\n //\n // Burn methods\n //\n\n // @dev Burns tokens belonging to the sender\n // @param _value Amount of token to be burned\n function burn(uint256 _value) public onlyOwner {\n // TODO: add a function & modifier to enable for all accounts without doing\n // a contract migration?\n super.burn(_value);\n }\n\n // @dev Burns tokens belonging to the specified address\n // @param _who The account whose tokens we're burning\n // @param _value Amount of token to be burned\n function burn(address _who, uint256 _value) public onlyOwner {\n _burn(_who, _value);\n }\n\n //\n // approveAndCall methods\n //\n\n // @dev Add spender to whitelist of spenders for approveAndCall\n // @param _spender Address to add\n function addCallSpenderWhitelist(address _spender) public onlyOwner {\n callSpenderWhitelist[_spender] = true;\n emit AddCallSpenderWhitelist(msg.sender, _spender);\n }\n\n // @dev Remove spender from whitelist of spenders for approveAndCall\n // @param _spender Address to remove\n function removeCallSpenderWhitelist(address _spender) public onlyOwner {\n delete callSpenderWhitelist[_spender];\n emit RemoveCallSpenderWhitelist(msg.sender, _spender);\n }\n\n // @dev Approve transfer of tokens and make a contract call in a single\n // @dev transaction. This allows a DApp to avoid requiring two MetaMask\n // @dev approvals for a single logical action, such as creating a listing,\n // @dev which requires the seller to approve a token transfer and the\n // @dev marketplace contract to transfer tokens from the seller.\n //\n // @dev This is based on the ERC827 function approveAndCall and avoids\n // @dev security issues by only working with a whitelisted set of _spender\n // @dev addresses. The other difference is that the combination of this\n // @dev function ensures that the proxied function call receives the\n // @dev msg.sender for this function as its first parameter.\n //\n // @param _spender The address that will spend the funds.\n // @param _value The amount of tokens to be spent.\n // @param _selector Function selector for function to be called.\n // @param _callParams Packed, encoded parameters, omitting the first parameter which is always msg.sender\n function approveAndCallWithSender(\n address _spender,\n uint256 _value,\n bytes4 _selector,\n bytes memory _callParams\n ) public payable returns (bool) {\n require(_spender != address(this), \"token contract can't be approved\");\n require(callSpenderWhitelist[_spender], \"spender not in whitelist\");\n\n require(super.approve(_spender, _value), \"approve failed\");\n\n bytes memory callData = abi.encodePacked(\n _selector,\n uint256(msg.sender),\n _callParams\n );\n // solium-disable-next-line security/no-call-value\n (bool success, ) = _spender.call.value(msg.value)(callData);\n require(success, \"proxied call failed\");\n return true;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./ERC20.sol\";\nimport \"../../access/roles/MinterRole.sol\";\n\n/**\n * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole},\n * which have permission to mint (create) new tokens as they see fit.\n *\n * At construction, the deployer of the contract is the only minter.\n */\ncontract ERC20Mintable is ERC20, MinterRole {\n /**\n * @dev See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the {MinterRole}.\n */\n function mint(address account, uint256 amount) public onlyMinter returns (bool) {\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./IERC20.sol\";\n\n/**\n * @dev Optional functions from the ERC20 standard.\n */\ncontract ERC20Detailed is IERC20 {\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\n * these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name, string memory symbol, uint8 decimals) public {\n _name = name;\n _symbol = symbol;\n _decimals = decimals;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view 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 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.\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 returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/mocks/WhitelistedPausableToken.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol\";\n\n/**\n * @title Contract for enforcing a list of addresses allowed to send or receive tokens\n * @dev Until the whitelist expiration expires, this contract only permits\n * token transfers in which an allowed transactor is either the sender or\n * recipient. Once the whitelist expiration passes, it becomes impossible to\n * re-enable the whitelist.\n *\n * This contract inherits from ERC20Pausable to enforce both pausing and\n * whitelists for transfer calls.\n */\ncontract WhitelistedPausableToken is ERC20Pausable {\n address public owner = msg.sender;\n\n // UNIX timestamp (in seconds) after which this whitelist no longer applies\n uint256 public whitelistExpiration;\n // While the whitelist is active, either the sender or recipient must be\n // in allowedTransactors.\n mapping(address => bool) public allowedTransactors;\n\n event SetWhitelistExpiration(uint256 expiration);\n event AllowedTransactorAdded(address sender);\n event AllowedTransactorRemoved(address sender);\n\n //\n // Functions for maintaining whitelist\n //\n\n modifier onlyOwner {\n require(msg.sender == owner);\n _;\n }\n modifier allowedTransfer(address _from, address _to) {\n require(\n // solium-disable-next-line operator-whitespace\n !whitelistActive() ||\n allowedTransactors[_from] ||\n allowedTransactors[_to],\n \"neither sender nor recipient are allowed\"\n );\n _;\n }\n\n function whitelistActive() public view returns (bool) {\n return block.timestamp < whitelistExpiration;\n }\n\n function addAllowedTransactor(address _transactor) public onlyOwner {\n emit AllowedTransactorAdded(_transactor);\n allowedTransactors[_transactor] = true;\n }\n\n function removeAllowedTransactor(address _transactor) public onlyOwner {\n emit AllowedTransactorRemoved(_transactor);\n delete allowedTransactors[_transactor];\n }\n\n /**\n * @dev Set the whitelist expiration, after which the whitelist no longer\n * applies.\n */\n function setWhitelistExpiration(uint256 _expiration) public onlyOwner {\n // allow only if whitelist expiration hasn't yet been set, or if the\n // whitelist expiration hasn't passed yet\n require(\n whitelistExpiration == 0 || whitelistActive(),\n \"an expired whitelist cannot be extended\"\n );\n // prevent possible mistakes in calling this function\n require(\n _expiration >= block.timestamp + 1 days,\n \"whitelist expiration not far enough into the future\"\n );\n emit SetWhitelistExpiration(_expiration);\n whitelistExpiration = _expiration;\n }\n\n //\n // ERC20 transfer functions that have been overridden to enforce the\n // whitelist.\n //\n\n function transfer(address _to, uint256 _value)\n public\n allowedTransfer(msg.sender, _to)\n returns (bool)\n {\n return super.transfer(_to, _value);\n }\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) public allowedTransfer(_from, _to) returns (bool) {\n return super.transferFrom(_from, _to, _value);\n }\n}\n" + }, + "contracts/mocks/MockCToken.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n IERC20,\n ERC20,\n ERC20Mintable\n} from \"@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol\";\nimport {\n ERC20Detailed\n} from \"@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\";\n\nimport { ICERC20 } from \"../strategies/ICompound.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\n\ncontract MockCToken is ICERC20, ERC20, ERC20Detailed, ERC20Mintable {\n using StableMath for uint256;\n\n IERC20 public underlyingToken;\n // underlying = cToken * exchangeRate\n // cToken = underlying / exchangeRate\n uint256 exchangeRate;\n address public comptroller;\n\n constructor(ERC20Detailed _underlyingToken, address _comptroller)\n public\n ERC20Detailed(\"cMock\", \"cMK\", 8)\n {\n uint8 underlyingDecimals = _underlyingToken.decimals();\n // if has 18 dp, exchange rate should be 1e26\n // if has 8 dp, exchange rate should be 1e18\n if (underlyingDecimals > 8) {\n exchangeRate = 10**uint256(18 + underlyingDecimals - 10);\n } else if (underlyingDecimals < 8) {\n // e.g. 18-8+6 = 16\n exchangeRate = 10**uint256(18 - 8 + underlyingDecimals);\n } else {\n exchangeRate = 1e18;\n }\n underlyingToken = _underlyingToken;\n comptroller = _comptroller;\n }\n\n function mint(uint256 mintAmount) external returns (uint256) {\n // Credit them with cToken\n _mint(msg.sender, mintAmount.divPrecisely(exchangeRate));\n // Take their reserve\n underlyingToken.transferFrom(msg.sender, address(this), mintAmount);\n return 0;\n }\n\n function redeem(uint256 redeemAmount) external returns (uint256) {\n uint256 tokenAmount = redeemAmount.mulTruncate(exchangeRate);\n // Burn the cToken\n _burn(msg.sender, redeemAmount);\n // Transfer underlying to caller\n underlyingToken.transfer(msg.sender, tokenAmount);\n return 0;\n }\n\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256) {\n uint256 cTokens = redeemAmount.divPrecisely(exchangeRate);\n // Burn the cToken\n _burn(msg.sender, cTokens);\n // Transfer underlying to caller\n underlyingToken.transfer(msg.sender, redeemAmount);\n return 0;\n }\n\n function balanceOfUnderlying(address owner) external returns (uint256) {\n uint256 cTokenBal = this.balanceOf(owner);\n return cTokenBal.mulTruncate(exchangeRate);\n }\n\n function updateExchangeRate() internal returns (uint256) {\n uint256 factor = 100002 * (10**13); // 0.002%\n exchangeRate = exchangeRate.mulTruncate(factor);\n }\n\n function exchangeRateStored() external view returns (uint256) {\n return exchangeRate;\n }\n\n function supplyRatePerBlock() external view returns (uint256) {\n return 141 * (10**8);\n }\n}\n" + }, + "contracts/strategies/ICompound.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @dev Compound C Token interface\n * Documentation: https://compound.finance/developers/ctokens\n */\ninterface ICERC20 {\n /**\n * @notice The mint function transfers an asset into the protocol, which begins accumulating\n * interest based on the current Supply Rate for the asset. The user receives a quantity of\n * cTokens equal to the underlying tokens supplied, divided by the current Exchange Rate.\n * @param mintAmount The amount of the asset to be supplied, in units of the underlying asset.\n * @return 0 on success, otherwise an Error codes\n */\n function mint(uint256 mintAmount) external returns (uint256);\n\n /**\n * @notice Sender redeems cTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of cTokens to redeem into underlying\n * @return uint 0=success, otherwise an error code.\n */\n function redeem(uint256 redeemTokens) external returns (uint256);\n\n /**\n * @notice The redeem underlying function converts cTokens into a specified quantity of the underlying\n * asset, and returns them to the user. The amount of cTokens redeemed is equal to the quantity of\n * underlying tokens received, divided by the current Exchange Rate. The amount redeemed must be less\n * than the user's Account Liquidity and the market's available liquidity.\n * @param redeemAmount The amount of underlying to be redeemed.\n * @return 0 on success, otherwise an error code.\n */\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256);\n\n /**\n * @notice The user's underlying balance, representing their assets in the protocol, is equal to\n * the user's cToken balance multiplied by the Exchange Rate.\n * @param owner The account to get the underlying balance of.\n * @return The amount of underlying currently owned by the account.\n */\n function balanceOfUnderlying(address owner) external returns (uint256);\n\n /**\n * @notice Calculates the exchange rate from the underlying to the CToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view returns (uint256);\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view returns (uint256);\n\n /**\n * @notice Get the supply rate per block for supplying the token to Compound.\n */\n function supplyRatePerBlock() external view returns (uint256);\n\n /**\n * @notice Address of the Compound Comptroller.\n */\n function comptroller() external view returns (address);\n}\n" + }, + "contracts/strategies/CompoundStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Compound Strategy\n * @notice Investment strategy for investing stablecoins via Compound\n * @author Origin Protocol Inc\n */\nimport { ICERC20 } from \"./ICompound.sol\";\nimport { IComptroller } from \"../interfaces/IComptroller.sol\";\nimport {\n IERC20,\n InitializableAbstractStrategy\n} from \"../utils/InitializableAbstractStrategy.sol\";\n\ncontract CompoundStrategy is InitializableAbstractStrategy {\n event SkippedWithdrawal(address asset, uint256 amount);\n\n /**\n * @dev Collect accumulated COMP and send to Vault.\n */\n function collectRewardToken() external onlyVault nonReentrant {\n // Claim COMP from Comptroller\n ICERC20 cToken = _getCTokenFor(assetsMapped[0]);\n IComptroller comptroller = IComptroller(cToken.comptroller());\n comptroller.claimComp(address(this));\n // Transfer COMP to Vault\n IERC20 rewardToken = IERC20(rewardTokenAddress);\n uint256 balance = rewardToken.balanceOf(address(this));\n emit RewardTokenCollected(vaultAddress, balance);\n rewardToken.safeTransfer(vaultAddress, balance);\n }\n\n /**\n * @dev Deposit asset into Compound\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n * @return amountDeposited Amount of asset that was deposited\n */\n function deposit(address _asset, uint256 _amount)\n external\n onlyVault\n nonReentrant\n {\n _deposit(_asset, _amount);\n }\n\n /**\n * @dev Deposit asset into Compound\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n * @return amountDeposited Amount of asset that was deposited\n */\n function _deposit(address _asset, uint256 _amount) internal {\n require(_amount > 0, \"Must deposit something\");\n ICERC20 cToken = _getCTokenFor(_asset);\n emit Deposit(_asset, address(cToken), _amount);\n require(cToken.mint(_amount) == 0, \"cToken mint failed\");\n }\n\n /**\n * @dev Deposit the entire balance of any supported asset into Compound\n */\n function depositAll() external onlyVault nonReentrant {\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n uint256 balance = IERC20(assetsMapped[i]).balanceOf(address(this));\n if (balance > 0) {\n _deposit(assetsMapped[i], balance);\n }\n }\n }\n\n /**\n * @dev Withdraw asset from Compound\n * @param _recipient Address to receive withdrawn asset\n * @param _asset Address of asset to withdraw\n * @param _amount Amount of asset to withdraw\n * @return amountWithdrawn Amount of asset that was withdrawn\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external onlyVault nonReentrant {\n require(_amount > 0, \"Must withdraw something\");\n require(_recipient != address(0), \"Must specify recipient\");\n\n ICERC20 cToken = _getCTokenFor(_asset);\n // If redeeming 0 cTokens, just skip, else COMP will revert\n uint256 cTokensToRedeem = _convertUnderlyingToCToken(cToken, _amount);\n if (cTokensToRedeem == 0) {\n emit SkippedWithdrawal(_asset, _amount);\n return;\n }\n\n emit Withdrawal(_asset, address(cToken), _amount);\n require(cToken.redeemUnderlying(_amount) == 0, \"Redeem failed\");\n IERC20(_asset).safeTransfer(_recipient, _amount);\n }\n\n /**\n * @dev Remove all assets from platform and send them to Vault contract.\n */\n function withdrawAll() external onlyVaultOrGovernor nonReentrant {\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n // Redeem entire balance of cToken\n ICERC20 cToken = _getCTokenFor(assetsMapped[i]);\n if (cToken.balanceOf(address(this)) > 0) {\n require(\n cToken.redeem(cToken.balanceOf(address(this))) == 0,\n \"Redeem failed\"\n );\n // Transfer entire balance to Vault\n IERC20 asset = IERC20(assetsMapped[i]);\n asset.safeTransfer(\n vaultAddress,\n asset.balanceOf(address(this))\n );\n }\n }\n }\n\n /**\n * @dev Get the total asset value held in the platform\n * This includes any interest that was generated since depositing\n * Compound exchange rate between the cToken and asset gradually increases,\n * causing the cToken to be worth more corresponding asset.\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance)\n {\n // Balance is always with token cToken decimals\n ICERC20 cToken = _getCTokenFor(_asset);\n balance = _checkBalance(cToken);\n }\n\n /**\n * @dev Get the total asset value held in the platform\n * underlying = (cTokenAmt * exchangeRate) / 1e18\n * @param _cToken cToken for which to check balance\n * @return balance Total value of the asset in the platform\n */\n function _checkBalance(ICERC20 _cToken)\n internal\n view\n returns (uint256 balance)\n {\n uint256 cTokenBalance = _cToken.balanceOf(address(this));\n uint256 exchangeRate = _cToken.exchangeRateStored();\n // e.g. 50e8*205316390724364402565641705 / 1e18 = 1.0265..e18\n balance = cTokenBalance.mul(exchangeRate).div(1e18);\n }\n\n /**\n * @dev Retuns bool indicating whether asset is supported by strategy\n * @param _asset Address of the asset\n */\n function supportsAsset(address _asset) external view returns (bool) {\n return assetToPToken[_asset] != address(0);\n }\n\n /**\n * @dev Approve the spending of all assets by their corresponding cToken,\n * if for some reason is it necessary.\n */\n function safeApproveAllTokens() external {\n uint256 assetCount = assetsMapped.length;\n for (uint256 i = 0; i < assetCount; i++) {\n address asset = assetsMapped[i];\n address cToken = assetToPToken[asset];\n // Safe approval\n IERC20(asset).safeApprove(cToken, 0);\n IERC20(asset).safeApprove(cToken, uint256(-1));\n }\n }\n\n /**\n * @dev Internal method to respond to the addition of new asset / cTokens\n * We need to approve the cToken and give it permission to spend the asset\n * @param _asset Address of the asset to approve\n * @param _cToken This cToken has the approval approval\n */\n function _abstractSetPToken(address _asset, address _cToken) internal {\n // Safe approval\n IERC20(_asset).safeApprove(_cToken, 0);\n IERC20(_asset).safeApprove(_cToken, uint256(-1));\n }\n\n /**\n * @dev Get the cToken wrapped in the ICERC20 interface for this asset.\n * Fails if the pToken doesn't exist in our mappings.\n * @param _asset Address of the asset\n * @return Corresponding cToken to this asset\n */\n function _getCTokenFor(address _asset) internal view returns (ICERC20) {\n address cToken = assetToPToken[_asset];\n require(cToken != address(0), \"cToken does not exist\");\n return ICERC20(cToken);\n }\n\n /**\n * @dev Converts an underlying amount into cToken amount\n * cTokenAmt = (underlying * 1e18) / exchangeRate\n * @param _cToken cToken for which to change\n * @param _underlying Amount of underlying to convert\n * @return amount Equivalent amount of cTokens\n */\n function _convertUnderlyingToCToken(ICERC20 _cToken, uint256 _underlying)\n internal\n view\n returns (uint256 amount)\n {\n uint256 exchangeRate = _cToken.exchangeRateStored();\n // e.g. 1e18*1e18 / 205316390724364402565641705 = 50e8\n // e.g. 1e8*1e18 / 205316390724364402565641705 = 0.45 or 0\n amount = _underlying.mul(1e18).div(exchangeRate);\n }\n}\n" + }, + "contracts/interfaces/IComptroller.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IComptroller {\n /**\n * @notice Claim all the comp accrued by holder in all markets\n * @param holder The address to claim COMP for\n */\n function claimComp(address holder) external;\n}\n" + }, + "contracts/mocks/MockAave.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n IAaveAToken,\n IAaveLendingPool,\n ILendingPoolAddressesProvider\n} from \"../strategies/IAave.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport {\n IERC20,\n ERC20,\n ERC20Mintable\n} from \"@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol\";\nimport {\n ERC20Detailed\n} from \"@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\";\n\n// 1. User calls 'getLendingPool'\n// 2. User calls 'deposit' (Aave)\n// - Deposit their underlying\n// - Mint aToken to them\n// 3. User calls redeem (aToken)\n// - Retrieve their aToken\n// - Return equal amount of underlying\n\ncontract MockAToken is ERC20Mintable, ERC20Detailed {\n address public lendingPool;\n IERC20 public underlyingToken;\n using SafeERC20 for IERC20;\n\n constructor(\n address _lendingPool,\n string memory _name,\n string memory _symbol,\n IERC20 _underlyingToken\n )\n public\n ERC20Detailed(\n _name,\n _symbol,\n ERC20Detailed(address(_underlyingToken)).decimals()\n )\n {\n lendingPool = _lendingPool;\n underlyingToken = _underlyingToken;\n addMinter(_lendingPool);\n }\n\n function redeem(uint256 _amount) external {\n // Redeem these a Tokens\n _burn(msg.sender, _amount);\n // For the underlying\n underlyingToken.safeTransferFrom(lendingPool, msg.sender, _amount);\n }\n}\n\ncontract MockAave is IAaveLendingPool, ILendingPoolAddressesProvider {\n using SafeERC20 for IERC20;\n using StableMath for uint256;\n\n mapping(address => address) reserveToAToken;\n address pool = address(this);\n address payable core = address(uint160(address(this)));\n uint256 factor;\n\n function addAToken(address _aToken, address _underlying) public {\n IERC20(_underlying).safeApprove(_aToken, 0);\n IERC20(_underlying).safeApprove(_aToken, uint256(-1));\n reserveToAToken[_underlying] = _aToken;\n }\n\n // set the reserve factor / basically the interest on deposit\n // in 18 precision\n // so 0.5% would be 5 * 10 ^ 15\n function setFactor(uint256 factor_) public {\n factor = factor_;\n }\n\n function deposit(\n address _reserve,\n uint256 _amount,\n uint16 /*_referralCode*/\n ) external {\n uint256 previousBal = IERC20(reserveToAToken[_reserve]).balanceOf(\n msg.sender\n );\n uint256 interest = previousBal.mulTruncate(factor);\n ERC20Mintable(reserveToAToken[_reserve]).mint(msg.sender, interest);\n // Take their reserve\n IERC20(_reserve).safeTransferFrom(msg.sender, address(this), _amount);\n // Credit them with aToken\n ERC20Mintable(reserveToAToken[_reserve]).mint(msg.sender, _amount);\n }\n\n function getLendingPool() external view returns (address) {\n return pool;\n }\n\n function getLendingPoolCore() external view returns (address payable) {\n return core;\n }\n}\n" + }, + "contracts/strategies/IAave.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @dev Interface for Aaves A Token\n * Documentation: https://developers.aave.com/#atokens\n */\ninterface IAaveAToken {\n /**\n * @notice Non-standard ERC20 function to redeem an _amount of aTokens for the underlying\n * asset, burning the aTokens during the process.\n * @param _amount Amount of aTokens\n */\n function redeem(uint256 _amount) external;\n\n /**\n * @notice returns the current total aToken balance of _user all interest collected included.\n * To obtain the user asset principal balance with interests excluded , ERC20 non-standard\n * method principalBalanceOf() can be used.\n */\n function balanceOf(address _user) external view returns (uint256);\n}\n\n/**\n * @dev Interface for Aaves Lending Pool\n * Documentation: https://developers.aave.com/#lendingpool\n */\ninterface IAaveLendingPool {\n /**\n * @notice Deposits a certain _amount of an asset specified by the _reserve parameter.\n * @dev The caller receives a certain amount of corresponding aTokens in exchange.\n * The amount of aTokens received depends on the corresponding aToken exchange rate.\n * LendingPoolCore must be approved to spend this reserve\n */\n function deposit(\n address _reserve,\n uint256 _amount,\n uint16 _referralCode\n ) external;\n}\n\n/**\n * @dev Interface for Aaves Lending Pool\n * Documentation: https://developers.aave.com/#lendingpooladdressesprovider\n */\ninterface ILendingPoolAddressesProvider {\n /**\n * @notice Get the current address for Aave LendingPool\n * @dev Lending pool is the core contract on which to call deposit\n */\n function getLendingPool() external view returns (address);\n\n /**\n * @notice Get the address for lendingPoolCore\n * @dev IMPORTANT - this is where _reserve must be approved before deposit\n */\n function getLendingPoolCore() external view returns (address payable);\n}\n" + }, + "contracts/strategies/AaveStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Aave Strategy\n * @notice Investment strategy for investing stablecoins via Aave\n * @author Origin Protocol Inc\n */\nimport \"./IAave.sol\";\nimport {\n IERC20,\n InitializableAbstractStrategy\n} from \"../utils/InitializableAbstractStrategy.sol\";\n\ncontract AaveStrategy is InitializableAbstractStrategy {\n uint16 constant referralCode = 92;\n\n /**\n * @dev Deposit asset into Aave\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n * @return amountDeposited Amount of asset that was deposited\n */\n function deposit(address _asset, uint256 _amount)\n external\n onlyVault\n nonReentrant\n {\n _deposit(_asset, _amount);\n }\n\n /**\n * @dev Deposit asset into Aave\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n * @return amountDeposited Amount of asset that was deposited\n */\n function _deposit(address _asset, uint256 _amount) internal {\n require(_amount > 0, \"Must deposit something\");\n IAaveAToken aToken = _getATokenFor(_asset);\n emit Deposit(_asset, address(aToken), _amount);\n _getLendingPool().deposit(_asset, _amount, referralCode);\n }\n\n /**\n * @dev Deposit the entire balance of any supported asset into Aave\n */\n function depositAll() external onlyVault nonReentrant {\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n uint256 balance = IERC20(assetsMapped[i]).balanceOf(address(this));\n if (balance > 0) {\n _deposit(assetsMapped[i], balance);\n }\n }\n }\n\n /**\n * @dev Withdraw asset from Aave\n * @param _recipient Address to receive withdrawn asset\n * @param _asset Address of asset to withdraw\n * @param _amount Amount of asset to withdraw\n * @return amountWithdrawn Amount of asset that was withdrawn\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external onlyVault nonReentrant {\n require(_amount > 0, \"Must withdraw something\");\n require(_recipient != address(0), \"Must specify recipient\");\n\n IAaveAToken aToken = _getATokenFor(_asset);\n emit Withdrawal(_asset, address(aToken), _amount);\n aToken.redeem(_amount);\n IERC20(_asset).safeTransfer(_recipient, _amount);\n }\n\n /**\n * @dev Remove all assets from platform and send them to Vault contract.\n */\n function withdrawAll() external onlyVaultOrGovernor nonReentrant {\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n // Redeem entire balance of aToken\n IAaveAToken aToken = _getATokenFor(assetsMapped[i]);\n uint256 balance = aToken.balanceOf(address(this));\n if (balance > 0) {\n aToken.redeem(balance);\n // Transfer entire balance to Vault\n IERC20 asset = IERC20(assetsMapped[i]);\n asset.safeTransfer(\n vaultAddress,\n asset.balanceOf(address(this))\n );\n }\n }\n }\n\n /**\n * @dev Get the total asset value held in the platform\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance)\n {\n // Balance is always with token aToken decimals\n IAaveAToken aToken = _getATokenFor(_asset);\n balance = aToken.balanceOf(address(this));\n }\n\n /**\n * @dev Retuns bool indicating whether asset is supported by strategy\n * @param _asset Address of the asset\n */\n function supportsAsset(address _asset) external view returns (bool) {\n return assetToPToken[_asset] != address(0);\n }\n\n /**\n * @dev Approve the spending of all assets by their corresponding aToken,\n * if for some reason is it necessary.\n */\n function safeApproveAllTokens() external onlyGovernor nonReentrant {\n uint256 assetCount = assetsMapped.length;\n address lendingPoolVault = _getLendingPoolCore();\n // approve the pool to spend the bAsset\n for (uint256 i = 0; i < assetCount; i++) {\n address asset = assetsMapped[i];\n // Safe approval\n IERC20(asset).safeApprove(lendingPoolVault, 0);\n IERC20(asset).safeApprove(lendingPoolVault, uint256(-1));\n }\n }\n\n /**\n * @dev Internal method to respond to the addition of new asset / aTokens\n * We need to approve the aToken and give it permission to spend the asset\n * @param _asset Address of the asset to approve\n * @param _aToken This aToken has the approval approval\n */\n function _abstractSetPToken(address _asset, address _aToken) internal {\n address lendingPoolVault = _getLendingPoolCore();\n IERC20(_asset).safeApprove(lendingPoolVault, 0);\n IERC20(_asset).safeApprove(lendingPoolVault, uint256(-1));\n }\n\n /**\n * @dev Get the aToken wrapped in the ICERC20 interface for this asset.\n * Fails if the pToken doesn't exist in our mappings.\n * @param _asset Address of the asset\n * @return Corresponding aToken to this asset\n */\n function _getATokenFor(address _asset) internal view returns (IAaveAToken) {\n address aToken = assetToPToken[_asset];\n require(aToken != address(0), \"aToken does not exist\");\n return IAaveAToken(aToken);\n }\n\n /**\n * @dev Get the current address of the Aave lending pool, which is the gateway to\n * depositing.\n * @return Current lending pool implementation\n */\n function _getLendingPool() internal view returns (IAaveLendingPool) {\n address lendingPool = ILendingPoolAddressesProvider(platformAddress)\n .getLendingPool();\n require(lendingPool != address(0), \"Lending pool does not exist\");\n return IAaveLendingPool(lendingPool);\n }\n\n /**\n * @dev Get the current address of the Aave lending pool core, which stores all the\n * reserve tokens in its vault.\n * @return Current lending pool core address\n */\n function _getLendingPoolCore() internal view returns (address payable) {\n address payable lendingPoolCore = ILendingPoolAddressesProvider(\n platformAddress\n )\n .getLendingPoolCore();\n require(\n lendingPoolCore != address(uint160(address(0))),\n \"Lending pool core does not exist\"\n );\n return lendingPoolCore;\n }\n}\n" + }, + "contracts/mocks/curve/MockCurvePool.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IMintableERC20 } from \"../MintableERC20.sol\";\nimport { ICurvePool } from \"../../strategies/ICurvePool.sol\";\nimport { StableMath } from \"../../utils/StableMath.sol\";\nimport \"../../utils/Helpers.sol\";\n\ncontract MockCurvePool is ERC20 {\n using StableMath for uint256;\n\n address[] public coins;\n address lpToken;\n\n constructor(address[3] memory _coins, address _lpToken) public {\n coins = _coins;\n lpToken = _lpToken;\n }\n\n // Returns the same amount of LP tokens in 1e18 decimals\n function add_liquidity(uint256[3] calldata _amounts, uint256 _minAmount)\n external\n {\n uint256 sum = 0;\n for (uint256 i = 0; i < _amounts.length; i++) {\n if (_amounts[i] > 0) {\n IERC20(coins[i]).transferFrom(\n msg.sender,\n address(this),\n _amounts[i]\n );\n uint256 assetDecimals = Helpers.getDecimals(coins[i]);\n // Convert to 1e18 and add to sum\n sum += _amounts[i].scaleBy(int8(18 - assetDecimals));\n }\n }\n // Hacky way of simulating slippage to check _minAmount\n if (sum == 29000e18) sum = 14500e18;\n require(sum >= _minAmount, \"Slippage ruined your day\");\n // Send LP token to sender, e.g. 3CRV\n IMintableERC20(lpToken).mint(sum);\n IERC20(lpToken).transfer(msg.sender, sum);\n }\n\n // Dumb implementation that returns the same amount\n function calc_withdraw_one_coin(uint256 _amount, int128 _index)\n public\n view\n returns (uint256)\n {\n uint256 assetDecimals = Helpers.getDecimals(coins[uint256(_index)]);\n return _amount.scaleBy(int8(assetDecimals - 18));\n }\n\n function remove_liquidity_one_coin(\n uint256 _amount,\n int128 _index,\n uint256 _minAmount\n ) external {\n IERC20(lpToken).transferFrom(msg.sender, address(this), _amount);\n uint256[] memory amounts = new uint256[](coins.length);\n amounts[uint256(_index)] = _amount;\n uint256 amount = calc_withdraw_one_coin(_amount, _index);\n IERC20(coins[uint256(_index)]).transfer(msg.sender, amount);\n }\n\n function get_virtual_price() external view returns (uint256) {\n return 1 * 10**18;\n }\n\n function remove_liquidity(uint256 _amount, uint256[3] memory _min_amounts)\n public\n {\n IERC20(lpToken).transferFrom(msg.sender, address(this), _amount);\n uint256 totalSupply = IERC20(lpToken).totalSupply();\n for (uint256 i = 0; i < 3; i++) {\n uint256 amount = _amount.div(totalSupply).mul(\n IERC20(coins[i]).balanceOf(address(this))\n );\n IERC20(coins[i]).transfer(msg.sender, amount);\n }\n }\n}\n" + }, + "contracts/mocks/MintableERC20.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMintableERC20 {\n function mint(uint256 value) external returns (bool);\n}\n\n/**\n * @title ERC20Mintable\n * @dev ERC20 minting logic\n */\ncontract MintableERC20 is IMintableERC20, ERC20 {\n /**\n * @dev Function to mint tokens\n * @param value The amount of tokens to mint.\n * @return A boolean that indicates if the operation was successful.\n */\n function mint(uint256 value) public returns (bool) {\n _mint(msg.sender, value);\n return true;\n }\n}\n" + }, + "contracts/mocks/MockWETH.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockWETH is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"WETH\";\n string public constant name = \"WETH\";\n}\n" + }, + "contracts/mocks/MockUSDT.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockUSDT is MintableERC20 {\n uint256 public constant decimals = 6;\n string public constant symbol = \"USDT\";\n string public constant name = \"USDT Coin\";\n}\n" + }, + "contracts/mocks/MockUSDC.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockUSDC is MintableERC20 {\n uint256 public constant decimals = 6;\n string public constant symbol = \"USDC\";\n string public constant name = \"USD Coin\";\n}\n" + }, + "contracts/mocks/MockTUSD.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockTUSD is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"TUSD\";\n string public constant name = \"TrueUSD\";\n}\n" + }, + "contracts/mocks/MockNonStandardToken.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\n/**\n * Mock token contract to simulate tokens that don't\n * throw/revert when a transfer/transferFrom call fails\n */\ncontract MockNonStandardToken is MintableERC20 {\n uint256 public constant decimals = 6;\n string public constant symbol = \"NonStandardToken\";\n string public constant name = \"NonStandardToken\";\n\n function transfer(address recipient, uint256 amount) public returns (bool) {\n if (balanceOf(msg.sender) < amount) {\n // Fail silently\n return false;\n }\n\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) public returns (bool) {\n if (balanceOf(sender) < amount) {\n // Fail silently\n return false;\n }\n\n _transfer(sender, recipient, amount);\n _approve(\n sender,\n _msgSender(),\n allowance(sender, _msgSender()).sub(\n amount,\n \"ERC20: transfer amount exceeds allowance\"\n )\n );\n return true;\n }\n}\n" + }, + "contracts/mocks/MockMintableUniswapPair.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\nimport \"./MockUniswapPair.sol\";\n\ncontract MockMintableUniswapPair is MockUniswapPair, MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"Uniswap V2\";\n string public constant name = \"UNI-V2\";\n\n constructor(\n address _token0,\n address _token1,\n uint112 _reserve0,\n uint112 _reserve1\n ) public MockUniswapPair(_token0, _token1, _reserve0, _reserve1) {}\n}\n" + }, + "contracts/mocks/MockUniswapPair.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IUniswapV2Pair } from \"../interfaces/uniswap/IUniswapV2Pair.sol\";\n\ncontract MockUniswapPair is IUniswapV2Pair {\n address tok0;\n address tok1;\n uint112 reserve0;\n uint112 reserve1;\n uint256 blockTimestampLast;\n\n bool public hasSynced = false;\n\n constructor(\n address _token0,\n address _token1,\n uint112 _reserve0,\n uint112 _reserve1\n ) public {\n tok0 = _token0;\n tok1 = _token1;\n reserve0 = _reserve0;\n reserve1 = _reserve1;\n blockTimestampLast = block.timestamp;\n }\n\n function token0() external view returns (address) {\n return tok0;\n }\n\n function token1() external view returns (address) {\n return tok1;\n }\n\n function getReserves()\n external\n view\n returns (\n uint112,\n uint112,\n uint32\n )\n {\n return (reserve0, reserve1, uint32(blockTimestampLast));\n }\n\n function setReserves(uint112 _reserve0, uint112 _reserve1) public {\n reserve0 = _reserve0;\n reserve1 = _reserve1;\n blockTimestampLast = block.timestamp;\n }\n\n // CAUTION This will not work if you setReserves multiple times over multiple different blocks because then it wouldn't be a continuous reserve factor over that blockTimestamp,\n // this assumes an even reserve ratio all the way through\n function price0CumulativeLast() external view returns (uint256) {\n return\n uint256(FixedPoint.fraction(reserve1, reserve0)._x) *\n blockTimestampLast;\n }\n\n function price1CumulativeLast() external view returns (uint256) {\n return\n uint256(FixedPoint.fraction(reserve0, reserve1)._x) *\n blockTimestampLast;\n }\n\n function sync() external {\n hasSynced = true;\n }\n\n function checkHasSynced() external view {\n require(hasSynced, \"Not synced\");\n }\n}\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 // returns a uq112x112 which represents the ratio of the numerator to the denominator\n // equivalent to encode(numerator).div(denominator)\n function fraction(uint112 numerator, uint112 denominator)\n internal\n pure\n returns (uq112x112 memory)\n {\n require(denominator > 0, \"FixedPoint: DIV_BY_ZERO\");\n return uq112x112((uint224(numerator) << 112) / denominator);\n }\n}\n" + }, + "contracts/interfaces/uniswap/IUniswapV2Pair.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IUniswapV2Pair {\n function token0() external view returns (address);\n\n function token1() external view returns (address);\n\n function getReserves()\n external\n view\n returns (\n uint112 reserve0,\n uint112 reserve1,\n uint32 blockTimestampLast\n );\n\n function price0CumulativeLast() external view returns (uint256);\n\n function price1CumulativeLast() external view returns (uint256);\n\n function sync() external;\n}\n" + }, + "contracts/mocks/MockEvilDAI.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\nimport { IVault } from \"../interfaces/IVault.sol\";\n\ncontract MockEvilDAI is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"DAI\";\n string public constant name = \"DAI\";\n address host;\n address realCoin;\n\n constructor(address _host, address _realCoin) public {\n host = _host;\n realCoin = _realCoin;\n }\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _amount\n ) public returns (bool) {\n // call mint again!\n if (_amount != 69) {\n IVault(host).mint(address(this), 69, 0);\n }\n return true;\n }\n}\n" + }, + "contracts/mocks/MockDAI.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockDAI is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"DAI\";\n string public constant name = \"DAI\";\n}\n" + }, + "contracts/mocks/MockCOMP.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockCOMP is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"COMP\";\n string public constant name = \"COMP\";\n}\n" + }, + "contracts/mocks/curve/MockCRVMinter.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IMintableERC20 } from \"../MintableERC20.sol\";\n\ncontract MockCRVMinter {\n address crv;\n\n constructor(address _crv) public {\n crv = _crv;\n }\n\n function mint(address _address) external {\n uint256 amount = 2e18;\n IMintableERC20(crv).mint(amount);\n IERC20(crv).transfer(_address, amount);\n }\n}\n" + }, + "contracts/mocks/curve/MockCRV.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../MintableERC20.sol\";\n\ncontract MockCRV is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"CRV\";\n string public constant name = \"Curve DAO Token\";\n}\n" + }, + "contracts/mocks/curve/Mock3CRV.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../MintableERC20.sol\";\n\ncontract Mock3CRV is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"3Crv\";\n string public constant name = \"Curve.fi DAI/USDC/USDT\";\n\n function mint(address to, uint256 value) public returns (bool) {\n _mint(to, value);\n return true;\n }\n\n function burnFrom(address from, uint256 value) public returns (bool) {\n _burn(from, value);\n return true;\n }\n}\n" + }, + "contracts/mocks/curve/MockCurveGauge.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\nimport { ICurveGauge } from \"../../strategies/ICurveGauge.sol\";\n\ncontract MockCurveGauge is ICurveGauge {\n mapping(address => uint256) private _balances;\n address lpToken;\n\n constructor(address _lpToken) public {\n lpToken = _lpToken;\n }\n\n function balanceOf(address account) public view returns (uint256) {\n return _balances[account];\n }\n\n function deposit(uint256 _value, address _account) external {\n IERC20(lpToken).transferFrom(msg.sender, address(this), _value);\n _balances[_account] += _value;\n }\n\n function withdraw(uint256 _value) external {\n IERC20(lpToken).transfer(msg.sender, _value);\n _balances[msg.sender] -= _value;\n }\n}\n" + }, + "contracts/timelock/Timelock.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Timelock Contract\n * @author Origin Protocol Inc\n */\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface CapitalPausable {\n function pauseCapital() external;\n\n function unpauseCapital() external;\n}\n\ncontract Timelock {\n using SafeMath for uint256;\n\n event NewAdmin(address indexed newAdmin);\n event NewPendingAdmin(address indexed newPendingAdmin);\n event NewDelay(uint256 indexed newDelay);\n event CancelTransaction(\n bytes32 indexed txHash,\n address indexed target,\n string signature,\n bytes data,\n uint256 eta\n );\n event ExecuteTransaction(\n bytes32 indexed txHash,\n address indexed target,\n string signature,\n bytes data,\n uint256 eta\n );\n event QueueTransaction(\n bytes32 indexed txHash,\n address indexed target,\n string signature,\n bytes data,\n uint256 eta\n );\n\n uint256 public constant GRACE_PERIOD = 3 days;\n uint256 public constant MINIMUM_DELAY = 1 minutes;\n uint256 public constant MAXIMUM_DELAY = 2 days;\n\n address public admin;\n address public pendingAdmin;\n uint256 public delay;\n\n mapping(bytes32 => bool) public queuedTransactions;\n\n /**\n * @dev Throws if called by any account other than the Admin.\n */\n modifier onlyAdmin() {\n require(msg.sender == admin, \"Caller is not the admin\");\n _;\n }\n\n constructor(address admin_, uint256 delay_) public {\n require(\n delay_ >= MINIMUM_DELAY,\n \"Timelock::constructor: Delay must exceed minimum delay.\"\n );\n require(\n delay_ <= MAXIMUM_DELAY,\n \"Timelock::setDelay: Delay must not exceed maximum delay.\"\n );\n\n admin = admin_;\n delay = delay_;\n }\n\n function setDelay(uint256 delay_) public {\n require(\n msg.sender == address(this),\n \"Timelock::setDelay: Call must come from Timelock.\"\n );\n require(\n delay_ >= MINIMUM_DELAY,\n \"Timelock::setDelay: Delay must exceed minimum delay.\"\n );\n require(\n delay_ <= MAXIMUM_DELAY,\n \"Timelock::setDelay: Delay must not exceed maximum delay.\"\n );\n delay = delay_;\n\n emit NewDelay(delay);\n }\n\n function acceptAdmin() public {\n require(\n msg.sender == pendingAdmin,\n \"Timelock::acceptAdmin: Call must come from pendingAdmin.\"\n );\n admin = msg.sender;\n pendingAdmin = address(0);\n\n emit NewAdmin(admin);\n }\n\n function setPendingAdmin(address pendingAdmin_) public onlyAdmin {\n pendingAdmin = pendingAdmin_;\n\n emit NewPendingAdmin(pendingAdmin);\n }\n\n function queueTransaction(\n address target,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) internal returns (bytes32) {\n require(\n msg.sender == admin,\n \"Timelock::queueTransaction: Call must come from admin.\"\n );\n require(\n eta >= getBlockTimestamp().add(delay),\n \"Timelock::queueTransaction: Estimated execution block must satisfy delay.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, signature, keccak256(data), eta)\n );\n queuedTransactions[txHash] = true;\n\n emit QueueTransaction(txHash, target, signature, data, eta);\n return txHash;\n }\n\n function cancelTransaction(\n address target,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) internal {\n require(\n msg.sender == admin,\n \"Timelock::cancelTransaction: Call must come from admin.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, signature, keccak256(data), eta)\n );\n queuedTransactions[txHash] = false;\n\n emit CancelTransaction(txHash, target, signature, data, eta);\n }\n\n function executeTransaction(\n address target,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) internal returns (bytes memory) {\n require(\n msg.sender == admin,\n \"Timelock::executeTransaction: Call must come from admin.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, signature, keccak256(data), eta)\n );\n require(\n queuedTransactions[txHash],\n \"Timelock::executeTransaction: Transaction hasn't been queued.\"\n );\n require(\n getBlockTimestamp() >= eta,\n \"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\"\n );\n require(\n getBlockTimestamp() <= eta.add(GRACE_PERIOD),\n \"Timelock::executeTransaction: Transaction is stale.\"\n );\n\n queuedTransactions[txHash] = false;\n\n bytes memory callData;\n\n if (bytes(signature).length == 0) {\n callData = data;\n } else {\n callData = abi.encodePacked(\n bytes4(keccak256(bytes(signature))),\n data\n );\n }\n\n (bool success, bytes memory returnData) = target.call(callData);\n require(\n success,\n \"Timelock::executeTransaction: Transaction execution reverted.\"\n );\n\n emit ExecuteTransaction(txHash, target, signature, data, eta);\n\n return returnData;\n }\n\n function getBlockTimestamp() internal view returns (uint256) {\n // solium-disable-next-line security/no-block-members\n return block.timestamp;\n }\n\n function pauseCapital(address target) external {\n require(\n msg.sender == admin,\n \"Timelock::pauseCapital: Call must come from admin.\"\n );\n CapitalPausable(target).pauseCapital();\n }\n\n function unpauseCapital(address target) external {\n require(\n msg.sender == admin,\n \"Timelock::unpauseCapital: Call must come from admin.\"\n );\n CapitalPausable(target).unpauseCapital();\n }\n}\n" + }, + "contracts/governance/Governor.sol": { + "content": "pragma solidity 0.5.11;\npragma experimental ABIEncoderV2;\n\nimport \"./../timelock/Timelock.sol\";\n\n// Modeled off of Compound's Governor Alpha\n// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol\ncontract Governor is Timelock {\n // @notice The total number of proposals\n uint256 public proposalCount;\n\n struct Proposal {\n // @notice Unique id for looking up a proposal\n uint256 id;\n // @notice Creator of the proposal\n address proposer;\n // @notice The timestamp that the proposal will be available for\n // execution, set once the vote succeeds\n uint256 eta;\n // @notice the ordered list of target addresses for calls to be made\n address[] targets;\n // @notice The ordered list of function signatures to be called\n string[] signatures;\n // @notice The ordered list of calldata to be passed to each call\n bytes[] calldatas;\n // @notice Flag marking whether the proposal has been executed\n bool executed;\n }\n\n // @notice The official record of all proposals ever proposed\n mapping(uint256 => Proposal) public proposals;\n\n // @notice An event emitted when a new proposal is created\n event ProposalCreated(\n uint256 id,\n address proposer,\n address[] targets,\n string[] signatures,\n bytes[] calldatas,\n string description\n );\n\n // @notice An event emitted when a proposal has been queued in the Timelock\n event ProposalQueued(uint256 id, uint256 eta);\n\n // @notice An event emitted when a proposal has been executed in the Timelock\n event ProposalExecuted(uint256 id);\n\n // @notice An event emitted when a proposal has been cancelled\n event ProposalCancelled(uint256 id);\n\n uint256 public constant MAX_OPERATIONS = 16;\n\n // @notice Possible states that a proposal may be in\n enum ProposalState { Pending, Queued, Expired, Executed }\n\n constructor(address admin_, uint256 delay_)\n public\n Timelock(admin_, delay_)\n {}\n\n /**\n * @notice Propose Governance call(s)\n * @param targets Ordered list of targeted addresses\n * @param signatures Orderd list of function signatures to be called\n * @param calldatas Orderded list of calldata to be passed with each call\n * @param description Description of the governance\n * @return uint256 id of the proposal\n */\n function propose(\n address[] memory targets,\n string[] memory signatures,\n bytes[] memory calldatas,\n string memory description\n ) public returns (uint256) {\n // Allow anyone to propose for now, since only admin can queue the\n // transaction it should be harmless, you just need to pay the gas\n require(\n targets.length == signatures.length &&\n targets.length == calldatas.length,\n \"Governor::propose: proposal function information arity mismatch\"\n );\n require(targets.length != 0, \"Governor::propose: must provide actions\");\n require(\n targets.length <= MAX_OPERATIONS,\n \"Governor::propose: too many actions\"\n );\n\n proposalCount++;\n Proposal memory newProposal = Proposal({\n id: proposalCount,\n proposer: msg.sender,\n eta: 0,\n targets: targets,\n signatures: signatures,\n calldatas: calldatas,\n executed: false\n });\n\n proposals[newProposal.id] = newProposal;\n\n emit ProposalCreated(\n newProposal.id,\n msg.sender,\n targets,\n signatures,\n calldatas,\n description\n );\n return newProposal.id;\n }\n\n /**\n * @notice Queue a proposal for execution\n * @param proposalId id of the proposal to queue\n */\n function queue(uint256 proposalId) public onlyAdmin {\n require(\n state(proposalId) == ProposalState.Pending,\n \"Governor::queue: proposal can only be queued if it is pending\"\n );\n Proposal storage proposal = proposals[proposalId];\n proposal.eta = block.timestamp.add(delay);\n\n for (uint256 i = 0; i < proposal.targets.length; i++) {\n _queueOrRevert(\n proposal.targets[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n proposal.eta\n );\n }\n\n emit ProposalQueued(proposal.id, proposal.eta);\n }\n\n /**\n * @notice Get the state of a proposal\n * @param proposalId id of the proposal\n * @return ProposalState\n */\n function state(uint256 proposalId) public view returns (ProposalState) {\n require(\n proposalCount >= proposalId && proposalId > 0,\n \"Governor::state: invalid proposal id\"\n );\n Proposal storage proposal = proposals[proposalId];\n if (proposal.executed) {\n return ProposalState.Executed;\n } else if (proposal.eta == 0) {\n return ProposalState.Pending;\n } else if (block.timestamp >= proposal.eta.add(GRACE_PERIOD)) {\n return ProposalState.Expired;\n } else {\n return ProposalState.Queued;\n }\n }\n\n function _queueOrRevert(\n address target,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) internal {\n require(\n !queuedTransactions[keccak256(\n abi.encode(target, signature, keccak256(data), eta)\n )],\n \"Governor::_queueOrRevert: proposal action already queued at eta\"\n );\n require(\n queuedTransactions[queueTransaction(target, signature, data, eta)],\n \"Governor::_queueOrRevert: failed to queue transaction\"\n );\n }\n\n /**\n * @notice Execute a proposal.\n * @param proposalId id of the proposal\n */\n function execute(uint256 proposalId) public {\n require(\n state(proposalId) == ProposalState.Queued,\n \"Governor::execute: proposal can only be executed if it is queued\"\n );\n Proposal storage proposal = proposals[proposalId];\n proposal.executed = true;\n for (uint256 i = 0; i < proposal.targets.length; i++) {\n executeTransaction(\n proposal.targets[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n proposal.eta\n );\n }\n emit ProposalExecuted(proposalId);\n }\n\n /**\n * @notice Cancel a proposal.\n * @param proposalId id of the proposal\n */\n function cancel(uint256 proposalId) public onlyAdmin {\n ProposalState proposalState = state(proposalId);\n\n require(\n proposalState == ProposalState.Queued ||\n proposalState == ProposalState.Pending,\n \"Governor::execute: proposal can only be cancelled if it is queued or pending\"\n );\n Proposal storage proposal = proposals[proposalId];\n proposal.eta = 1; // To mark the proposal as `Expired`\n for (uint256 i = 0; i < proposal.targets.length; i++) {\n cancelTransaction(\n proposal.targets[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n proposal.eta\n );\n }\n emit ProposalCancelled(proposalId);\n }\n\n /**\n * @notice Get the actions that a proposal will take.\n * @param proposalId id of the proposal\n */\n function getActions(uint256 proposalId)\n public\n view\n returns (\n address[] memory targets,\n string[] memory signatures,\n bytes[] memory calldatas\n )\n {\n Proposal storage p = proposals[proposalId];\n return (p.targets, p.signatures, p.calldatas);\n }\n}\n" + }, + "contracts/compensation/CompensationClaims.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\n/**\n * @title Compensation Claims\n * @author Origin Protocol Inc\n * @dev Airdrop for ERC20 tokens.\n *\n * Provides a coin airdrop with a verification period in which everyone\n * can check that all claims are correct before any actual funds are moved\n * to the contract.\n *\n * - Users can claim funds during the claim period.\n *\n * - The adjuster can set the amount of each user's claim,\n * but only when unlocked, and not during the claim period.\n *\n * - The governor can unlock and lock the adjuster, outside the claim period.\n * - The governor can start the claim period, if it's not started.\n * - The governor can collect any remaining funds after the claim period is over.\n *\n * Intended use sequence:\n *\n * 1. Governor unlocks the adjuster\n * 2. Adjuster uploads claims\n * 3. Governor locks the adjuster\n * 4. Everyone verifies that the claim amounts and totals are correct\n * 5. Payout funds are moved to the contract\n * 6. The claim period starts\n * 7. Users claim funds\n * 8. The claim period ends\n * 9. Governor can collect any remaing funds\n *\n */\ncontract CompensationClaims is Governable {\n address public adjuster;\n address public token;\n uint256 public end;\n uint256 public totalClaims;\n mapping(address => uint256) claims;\n bool public isAdjusterLocked;\n\n using SafeMath for uint256;\n\n event Claim(address indexed recipient, uint256 amount);\n event ClaimSet(address indexed recipient, uint256 amount);\n event Start(uint256 end);\n event Lock();\n event Unlock();\n event Collect(address indexed coin, uint256 amount);\n\n constructor(address _token, address _adjuster) public onlyGovernor {\n token = _token;\n adjuster = _adjuster;\n isAdjusterLocked = true;\n }\n\n function balanceOf(address _account) external view returns (uint256) {\n return claims[_account];\n }\n\n function decimals() external view returns (uint8) {\n return IERC20Decimals(token).decimals();\n }\n\n /* -- User -- */\n\n function claim(address _recipient) external onlyInClaimPeriod nonReentrant {\n uint256 amount = claims[_recipient];\n require(amount > 0, \"Amount must be greater than 0\");\n claims[_recipient] = 0;\n totalClaims = totalClaims.sub(amount);\n SafeERC20.safeTransfer(IERC20(token), _recipient, amount);\n emit Claim(_recipient, amount);\n }\n\n /* -- Adjustor -- */\n\n function setClaims(\n address[] calldata _addresses,\n uint256[] calldata _amounts\n ) external notInClaimPeriod onlyUnlockedAdjuster {\n require(\n _addresses.length == _amounts.length,\n \"Addresses and amounts must match\"\n );\n uint256 len = _addresses.length;\n for (uint256 i = 0; i < len; i++) {\n address recipient = _addresses[i];\n uint256 newAmount = _amounts[i];\n uint256 oldAmount = claims[recipient];\n claims[recipient] = newAmount;\n totalClaims = totalClaims.add(newAmount).sub(oldAmount);\n emit ClaimSet(recipient, newAmount);\n }\n }\n\n /* -- Governor -- */\n\n function lockAdjuster() external onlyGovernor notInClaimPeriod {\n _lockAdjuster();\n }\n\n function _lockAdjuster() internal {\n isAdjusterLocked = true;\n emit Lock();\n }\n\n function unlockAdjuster() external onlyGovernor notInClaimPeriod {\n isAdjusterLocked = false;\n emit Unlock();\n }\n\n function start(uint256 _seconds)\n external\n onlyGovernor\n notInClaimPeriod\n nonReentrant\n {\n require(totalClaims > 0, \"No claims\");\n uint256 funding = IERC20(token).balanceOf(address(this));\n require(funding >= totalClaims, \"Insufficient funds for all claims\");\n _lockAdjuster();\n end = block.timestamp.add(_seconds);\n require(end.sub(block.timestamp) < 31622400, \"Duration too long\"); // 31622400 = 366*24*60*60\n emit Start(end);\n }\n\n function collect(address _coin)\n external\n onlyGovernor\n notInClaimPeriod\n nonReentrant\n {\n uint256 amount = IERC20(_coin).balanceOf(address(this));\n SafeERC20.safeTransfer(IERC20(_coin), address(governor()), amount);\n emit Collect(_coin, amount);\n }\n\n /* -- modifiers -- */\n\n modifier onlyInClaimPeriod() {\n require(block.timestamp <= end, \"Should be in claim period\");\n _;\n }\n\n modifier notInClaimPeriod() {\n require(block.timestamp > end, \"Should not be in claim period\");\n _;\n }\n\n modifier onlyUnlockedAdjuster() {\n require(isAdjusterLocked == false, \"Adjuster must be unlocked\");\n require(msg.sender == adjuster, \"Must be adjuster\");\n _;\n }\n}\n\ninterface IERC20Decimals {\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/governance/InitializableGovernable.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD InitializableGovernable Contract\n * @author Origin Protocol Inc\n */\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\n\nimport { Governable } from \"./Governable.sol\";\n\ncontract InitializableGovernable is Governable, Initializable {\n function _initialize(address _newGovernor) internal {\n _changeGovernor(_newGovernor);\n }\n}\n" + }, + "contracts/crytic/PropertiesOUSDTransferable.sol": { + "content": "import \"./interfaces.sol\";\nimport \"../token/OUSD.sol\";\n\ncontract PropertiesOUSDTransferable is CryticInterface, OUSD {\n function init_total_supply() public returns (bool) {\n return\n this.totalSupply() >= 0 && this.totalSupply() == initialTotalSupply;\n }\n\n function init_owner_balance() public returns (bool) {\n return initialBalance_owner == this.balanceOf(crytic_owner);\n }\n\n function init_user_balance() public returns (bool) {\n return initialBalance_user == this.balanceOf(crytic_user);\n }\n\n function init_attacker_balance() public returns (bool) {\n return initialBalance_attacker == this.balanceOf(crytic_attacker);\n }\n\n function init_caller_balance() public returns (bool) {\n return this.balanceOf(msg.sender) > 0;\n }\n\n function init_total_supply_is_balances() public returns (bool) {\n return\n this.balanceOf(crytic_owner) +\n this.balanceOf(crytic_user) +\n this.balanceOf(crytic_attacker) ==\n this.totalSupply();\n }\n\n function crytic_zero_always_empty_ERC20Properties() public returns (bool) {\n return this.balanceOf(address(0x0)) == 0;\n }\n\n function crytic_approve_overwrites() public returns (bool) {\n bool approve_return;\n approve_return = approve(crytic_user, 10);\n require(approve_return);\n approve_return = approve(crytic_user, 20);\n require(approve_return);\n return this.allowance(msg.sender, crytic_user) == 20;\n }\n\n function crytic_less_than_total_ERC20Properties() public returns (bool) {\n return this.balanceOf(msg.sender) <= totalSupply();\n }\n\n function crytic_revert_transfer_to_zero_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n if (this.balanceOf(msg.sender) == 0) {\n revert();\n }\n return transfer(address(0x0), this.balanceOf(msg.sender));\n }\n\n function crytic_revert_transferFrom_to_zero_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n if (balance == 0) {\n revert();\n }\n approve(msg.sender, balance);\n return\n transferFrom(msg.sender, address(0x0), this.balanceOf(msg.sender));\n }\n\n function crytic_self_transferFrom_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n bool approve_return = approve(msg.sender, balance);\n bool transfer_return = transferFrom(msg.sender, msg.sender, balance);\n return\n (this.balanceOf(msg.sender) == balance) &&\n approve_return &&\n transfer_return;\n }\n\n function crytic_self_transferFrom_to_other_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n bool approve_return = approve(msg.sender, balance);\n address other = crytic_user;\n if (other == msg.sender) {\n other = crytic_owner;\n }\n bool transfer_return = transferFrom(msg.sender, other, balance);\n return\n (this.balanceOf(msg.sender) == 0) &&\n approve_return &&\n transfer_return;\n }\n\n function crytic_self_transfer_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n bool transfer_return = transfer(msg.sender, balance);\n return (this.balanceOf(msg.sender) == balance) && transfer_return;\n }\n\n function crytic_transfer_to_other_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n address other = crytic_user;\n if (other == msg.sender) {\n other = crytic_owner;\n }\n if (balance >= 1) {\n bool transfer_other = transfer(other, 1);\n return\n (this.balanceOf(msg.sender) == balance - 1) &&\n (this.balanceOf(other) >= 1) &&\n transfer_other;\n }\n return true;\n }\n\n function crytic_revert_transfer_to_user_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n if (balance == (2**128 - 1)) return true;\n bool transfer_other = transfer(crytic_user, balance + 1);\n return transfer_other;\n }\n}\n" + }, + "contracts/crytic/interfaces.sol": { + "content": "contract CryticInterface {\n address internal crytic_owner = address(\n 0x627306090abaB3A6e1400e9345bC60c78a8BEf57\n );\n address internal crytic_user = address(\n 0xf17f52151EbEF6C7334FAD080c5704D77216b732\n );\n address internal crytic_attacker = address(\n 0xC5fdf4076b8F3A5357c5E395ab970B5B54098Fef\n );\n uint256 internal initialTotalSupply;\n uint256 internal initialBalance_owner;\n uint256 internal initialBalance_user;\n uint256 internal initialBalance_attacker;\n}\n" + }, + "contracts/crytic/TestOUSDTransferable.sol": { + "content": "import \"./PropertiesOUSDTransferable.sol\";\n\ncontract TestOUSDTransferable is PropertiesOUSDTransferable {\n constructor() public {\n // Existing addresses:\n // - crytic_owner: If the contract has an owner, it must be crytic_owner\n // - crytic_user: Legitimate user\n // - crytic_attacker: Attacker\n //\n // Add below a minimal configuration:\n // - crytic_owner must have some tokens\n // - crytic_user must have some tokens\n // - crytic_attacker must have some tokens\n\n rebasingCredits = 0;\n rebasingCreditsPerToken = 1e18;\n vaultAddress = crytic_owner;\n nonRebasingSupply = 0;\n\n initialTotalSupply = ~uint128(0);\n initialBalance_owner = initialTotalSupply / 3;\n _mint(crytic_owner, initialBalance_owner);\n initialBalance_user = initialTotalSupply / 3;\n _mint(crytic_user, initialBalance_user);\n initialBalance_attacker = initialTotalSupply / 3;\n _mint(crytic_attacker, initialBalance_attacker);\n }\n\n function initialize(\n string calldata _nameArg,\n string calldata _symbolArg,\n address _vaultAddress\n ) external {\n revert();\n } // We don't need to call initialize\n}\n" + }, + "contracts/buyback/BuybackConstructor.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { Governable } from \"../governance/Governable.sol\";\n\nimport { IUniswapV2Router } from \"../interfaces/uniswap/IUniswapV2Router02.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract BuybackConstructor is Governable {\n using SafeERC20 for IERC20;\n\n event UniswapUpdated(address _address);\n\n // Address of Uniswap\n address public uniswapAddr = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;\n\n // Address of OUSD Vault\n address public vaultAddr = 0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70;\n\n // Swap from OUSD\n IERC20 ousd = IERC20(0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86);\n\n // Swap to OGN\n IERC20 ogn = IERC20(0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26);\n\n // USDT for Uniswap path\n IERC20 usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n\n constructor(\n address _uniswapAddr,\n address _vaultAddr,\n address _ousd,\n address _ogn,\n address _usdt\n ) public {\n uniswapAddr = _uniswapAddr;\n vaultAddr = _vaultAddr;\n ousd = IERC20(_ousd);\n ogn = IERC20(_ogn);\n usdt = IERC20(_usdt);\n // Give approval to Uniswap router for OUSD, this is handled\n // by setUniswapAddr in the production contract\n ousd.safeApprove(uniswapAddr, 0);\n ousd.safeApprove(uniswapAddr, uint256(-1));\n }\n\n /**\n * @dev Verifies that the caller is the OUSD Vault.\n */\n modifier onlyVault() {\n require(vaultAddr == msg.sender, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @dev Set address of Uniswap for performing liquidation of strategy reward\n * tokens. Setting to 0x0 will pause swaps.\n * @param _address Address of Uniswap\n */\n function setUniswapAddr(address _address) external onlyGovernor {\n uniswapAddr = _address;\n // Give Uniswap unlimited OUSD allowance\n ousd.safeApprove(uniswapAddr, 0);\n ousd.safeApprove(uniswapAddr, uint256(-1));\n emit UniswapUpdated(_address);\n }\n\n /**\n * @dev Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible\n * protocol (e.g. Sushiswap)\n **/\n function swap() external onlyVault {\n if (uniswapAddr == address(0)) return;\n\n uint256 sourceAmount = ousd.balanceOf(address(this));\n if (sourceAmount < 1000 * 1e18) return;\n\n // Uniswap redemption path\n address[] memory path = new address[](4);\n path[0] = address(ousd);\n path[1] = address(usdt);\n path[2] = IUniswapV2Router(uniswapAddr).WETH();\n path[3] = address(ogn);\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\n sourceAmount,\n uint256(0),\n path,\n address(this),\n now\n );\n }\n\n /**\n * @notice Owner function to withdraw a specific amount of a token\n */\n function transferToken(address token, uint256 amount)\n external\n onlyGovernor\n nonReentrant\n {\n IERC20(token).safeTransfer(_governor(), amount);\n }\n}\n" + }, + "contracts/mocks/MockVault.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { VaultCore } from \"../vault/VaultCore.sol\";\nimport { VaultInitializer } from \"../vault/VaultInitializer.sol\";\n\ncontract MockVault is VaultCore, VaultInitializer {\n uint256 storedTotalValue;\n\n function setTotalValue(uint256 _totalValue) public {\n storedTotalValue = _totalValue;\n }\n\n function totalValue() external view returns (uint256) {\n return storedTotalValue;\n }\n\n function _totalValue() internal view returns (uint256) {\n return storedTotalValue;\n }\n\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor {\n maxSupplyDiff = _maxSupplyDiff;\n }\n}\n" + }, + "contracts/vault/VaultInitializer.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD VaultInitializer Contract\n * @notice The Vault contract initializes the vault.\n * @author Origin Protocol Inc\n */\n\nimport \"./VaultStorage.sol\";\n\ncontract VaultInitializer is VaultStorage {\n function initialize(address _priceProvider, address _ousd)\n external\n onlyGovernor\n initializer\n {\n require(_priceProvider != address(0), \"PriceProvider address is zero\");\n require(_ousd != address(0), \"oUSD address is zero\");\n\n oUSD = OUSD(_ousd);\n\n priceProvider = _priceProvider;\n\n rebasePaused = false;\n capitalPaused = true;\n\n // Initial redeem fee of 0 basis points\n redeemFeeBps = 0;\n // Initial Vault buffer of 0%\n vaultBuffer = 0;\n // Initial allocate threshold of 25,000 OUSD\n autoAllocateThreshold = 25000e18;\n // Threshold for rebasing\n rebaseThreshold = 1000e18;\n }\n}\n" + }, + "contracts/vault/Vault.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD VaultInitializer Contract\n * @notice The VaultInitializer sets up the initial contract.\n * @author Origin Protocol Inc\n */\nimport { VaultInitializer } from \"./VaultInitializer.sol\";\nimport { VaultAdmin } from \"./VaultAdmin.sol\";\n\ncontract Vault is VaultInitializer, VaultAdmin {}\n" + }, + "contracts/mocks/MockChainlinkOracleFeed.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../interfaces/chainlink/AggregatorV3Interface.sol\";\n\ncontract MockChainlinkOracleFeed is AggregatorV3Interface {\n int256 price;\n uint8 numDecimals;\n\n constructor(int256 _price, uint8 _decimals) public {\n price = _price;\n numDecimals = _decimals;\n }\n\n function decimals() external view returns (uint8) {\n return numDecimals;\n }\n\n function description() external view returns (string memory) {\n return \"MockOracleEthFeed\";\n }\n\n function version() external view returns (uint256) {\n return 1;\n }\n\n function setPrice(int256 _price) public {\n price = _price;\n }\n\n function setDecimals(uint8 _decimals) public {\n numDecimals = _decimals;\n }\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n )\n {\n roundId = _roundId;\n answer = price;\n startedAt = 0;\n updatedAt = 0;\n answeredInRound = 0;\n }\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n )\n {\n roundId = 0;\n answer = price;\n startedAt = 0;\n updatedAt = 0;\n answeredInRound = 0;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "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/contracts/deployments/rinkeby/.migrations.json b/contracts/deployments/rinkeby/.migrations.json index 19f494352c..1d1443db32 100644 --- a/contracts/deployments/rinkeby/.migrations.json +++ b/contracts/deployments/rinkeby/.migrations.json @@ -13,5 +13,6 @@ "012_upgrades": 1612292067, "013_trustee": 1612380511, "014_3pool_strategy": 1612999014, - "015_flipper": 1613166556 + "015_flipper": 1613166556, + "016_chainlink_and_buyback": 1616624684 } \ No newline at end of file diff --git a/contracts/deployments/rinkeby/Buyback.json b/contracts/deployments/rinkeby/Buyback.json new file mode 100644 index 0000000000..481e5c76e4 --- /dev/null +++ b/contracts/deployments/rinkeby/Buyback.json @@ -0,0 +1,255 @@ +{ + "address": "0x37f91c38F57b382bf9A40b2640c998Ed172f5bdA", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "uniswapAddr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claimGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "swap", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setUniswapAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isGovernor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultAddr", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "UniswapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "PendingGovernorshipTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "GovernorshipTransferred", + "type": "event" + } + ], + "transactionHash": "0x6119a0a40b6073f0b3b3ece131aff93e34c98a88d9b7aa21ff2eaddb4d8d7dc8", + "receipt": { + "to": null, + "from": "0xD85A569F3C26f81070544451131c742283360400", + "contractAddress": "0x37f91c38F57b382bf9A40b2640c998Ed172f5bdA", + "transactionIndex": 4, + "gasUsed": "887967", + "logsBloom": "0x00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000400000000000000000040000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000004000000000040000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000020000000000000000000000000000000000000000400000000000000000000000000", + "blockHash": "0x63e8cab35b01bb12f4f79ded8f82dc8795a39346ff7db559546fe3e5b331448e", + "transactionHash": "0x6119a0a40b6073f0b3b3ece131aff93e34c98a88d9b7aa21ff2eaddb4d8d7dc8", + "logs": [ + { + "transactionIndex": 4, + "blockNumber": 8292735, + "transactionHash": "0x6119a0a40b6073f0b3b3ece131aff93e34c98a88d9b7aa21ff2eaddb4d8d7dc8", + "address": "0x37f91c38F57b382bf9A40b2640c998Ed172f5bdA", + "topics": [ + "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000d85a569f3c26f81070544451131c742283360400" + ], + "data": "0x", + "logIndex": 14, + "blockHash": "0x63e8cab35b01bb12f4f79ded8f82dc8795a39346ff7db559546fe3e5b331448e" + } + ], + "blockNumber": 8292735, + "cumulativeGasUsed": "1392680", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "86605db9d81ca0a1790de251140fb0d9", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"swap\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setUniswapAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"setUniswapAddr(address)\":{\"details\":\"Set address of Uniswap for performing liquidation of strategy reward tokens. Setting to 0x0 will pause swaps.\",\"params\":{\"_address\":\"Address of Uniswap\"}},\"swap()\":{\"details\":\"Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible protocol (e.g. Sushiswap)*\"},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}}}},\"userdoc\":{\"methods\":{\"transferToken(address,uint256)\":{\"notice\":\"Owner function to withdraw a specific amount of a token\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/buyback/Buyback.sol\":\"Buyback\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"contracts/buyback/Buyback.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\nimport { IUniswapV2Router } from \\\"../interfaces/uniswap/IUniswapV2Router02.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\ncontract Buyback is Governable {\\n using SafeERC20 for IERC20;\\n\\n event UniswapUpdated(address _address);\\n\\n // Address of Uniswap\\n address public uniswapAddr = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;\\n\\n // Address of OUSD Vault\\n address constant public vaultAddr = 0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70;\\n\\n // Swap from OUSD\\n IERC20 constant ousd = IERC20(0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86);\\n\\n // Swap to OGN\\n IERC20 constant ogn = IERC20(0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26);\\n\\n // USDT for Uniswap path\\n IERC20 constant usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);\\n\\n /**\\n * @dev Verifies that the caller is the OUSD Vault.\\n */\\n modifier onlyVault() {\\n require(vaultAddr == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @dev Set address of Uniswap for performing liquidation of strategy reward\\n * tokens. Setting to 0x0 will pause swaps.\\n * @param _address Address of Uniswap\\n */\\n function setUniswapAddr(address _address) external onlyGovernor {\\n uniswapAddr = _address;\\n // Give Uniswap unlimited OUSD allowance\\n ousd.safeApprove(uniswapAddr, 0);\\n ousd.safeApprove(uniswapAddr, uint256(-1));\\n emit UniswapUpdated(_address);\\n }\\n\\n /**\\n * @dev Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible\\n * protocol (e.g. Sushiswap)\\n **/\\n function swap() external onlyVault {\\n if (uniswapAddr == address(0)) return;\\n\\n uint256 sourceAmount = ousd.balanceOf(address(this));\\n if (sourceAmount < 1000 * 1e18) return;\\n\\n // Uniswap redemption path\\n address[] memory path = new address[](4);\\n path[0] = address(ousd);\\n path[1] = address(usdt);\\n path[2] = IUniswapV2Router(uniswapAddr).WETH();\\n path[3] = address(ogn);\\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\\n sourceAmount,\\n uint256(0),\\n path,\\n address(this),\\n now\\n );\\n }\\n\\n /**\\n * @notice Owner function to withdraw a specific amount of a token\\n */\\n function transferToken(address token, uint256 amount)\\n external\\n onlyGovernor\\n nonReentrant\\n {\\n IERC20(token).safeTransfer(_governor(), amount);\\n }\\n}\\n\",\"keccak256\":\"0x69fcccff4a3b6197eab8d67379270817542de29c783520e9743a167941763dc2\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/uniswap/IUniswapV2Router02.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IUniswapV2Router {\\n function WETH() external pure returns (address);\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address[] calldata path,\\n address to,\\n uint256 deadline\\n ) external returns (uint256[] memory amounts);\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n );\\n}\\n\",\"keccak256\":\"0x33943cfab99996faa745df3c21b95b3ed49783b4c3392e4c71e25f6712af509b\"}},\"version\":1}", + "bytecode": "0x6080604052600080546001600160a01b031916737a250d5630b4cf539739df2c5dacb4c659f2488d17905561003c336001600160e01b0361009216565b61004d6001600160e01b036100a416565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36100b7565b600080516020610efc83398151915255565b600080516020610efc8339815191525490565b610e36806100c66000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80638119c065116100665780638119c065146100fa578063aea173d514610102578063c7af335214610128578063d27567f214610144578063d38bfff41461014c57610093565b80630c340a24146100985780631072cbea146100bc578063128a8b05146100ea5780635d36b190146100f2575b600080fd5b6100a0610172565b604080516001600160a01b039092168252519081900360200190f35b6100e8600480360360408110156100d257600080fd5b506001600160a01b038135169060200135610181565b005b6100a0610270565b6100e861027f565b6100e86102e1565b6100e86004803603602081101561011857600080fd5b50356001600160a01b03166106dc565b6101306107e9565b604080519115158252519081900360200190f35b6100a061080c565b6100e86004803603602081101561016257600080fd5b50356001600160a01b0316610824565b600061017c6108cd565b905090565b6101896107e9565b6101d7576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac453580546002811415610241576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556102676102506108cd565b6001600160a01b038616908563ffffffff6108f216565b50600190555050565b6000546001600160a01b031681565b610287610949565b6001600160a01b0316336001600160a01b0316146102d65760405162461bcd60e51b8152600401808060200182810382526030815260200180610dd26030913960400191505060405180910390fd5b6102df3361096e565b565b73e75d77b1865ae93c7eaa3040b038d7aa7bc02f703314610349576040805162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865205661756c74000000000000000000604482015290519081900360640190fd5b6000546001600160a01b031661035e576102df565b604080516370a0823160e01b81523060048201529051600091732a8e1e676ec238d8a992307b495b45b3feaa5e86916370a0823191602480820192602092909190829003018186803b1580156103b357600080fd5b505afa1580156103c7573d6000803e3d6000fd5b505050506040513d60208110156103dd57600080fd5b50519050683635c9adc5dea000008110156103f857506102df565b60408051600480825260a0820190925260609160208201608080388339019050509050732a8e1e676ec238d8a992307b495b45b3feaa5e868160008151811061043d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073dac17f958d2ee523a2206206994597c13d831ec78160018151811061047f57fe5b6001600160a01b03928316602091820292909201810191909152600054604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b1580156104d357600080fd5b505afa1580156104e7573d6000803e3d6000fd5b505050506040513d60208110156104fd57600080fd5b505181518290600290811061050e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050738207c1ffc5b6804f6024322ccf34f29c3541ae268160038151811061055057fe5b6001600160a01b03928316602091820292909201810191909152600080546040516338ed173960e01b815260048101878152602482018490523060648301819052426084840181905260a060448501908152895160a4860152895195909816976338ed1739978b97968b969495939460c4019187810191028083838b5b838110156105e55781810151838201526020016105cd565b505050509050019650505050505050600060405180830381600087803b15801561060e57600080fd5b505af1158015610622573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561064b57600080fd5b810190808051604051939291908464010000000082111561066b57600080fd5b90830190602082018581111561068057600080fd5b825186602082028301116401000000008211171561069d57600080fd5b82525081516020918201928201910280838360005b838110156106ca5781810151838201526020016106b2565b50505050905001604052505050505050565b6106e46107e9565b610732576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038381169190911780835561077692732a8e1e676ec238d8a992307b495b45b3feaa5e86929190911690610a1c565b6000546107aa90732a8e1e676ec238d8a992307b495b45b3feaa5e86906001600160a01b031660001963ffffffff610a1c16565b604080516001600160a01b038316815290517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b60006107f36108cd565b6001600160a01b0316336001600160a01b031614905090565b73e75d77b1865ae93c7eaa3040b038d7aa7bc02f7081565b61082c6107e9565b61087a576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b61088381610b2f565b806001600160a01b03166108956108cd565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610944908490610b53565b505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b0381166109c9576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b03166109db6108cd565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3610a1981610d11565b50565b801580610aa2575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015610a7457600080fd5b505afa158015610a88573d6000803e3d6000fd5b505050506040513d6020811015610a9e57600080fd5b5051155b610add5760405162461bcd60e51b8152600401808060200182810382526036815260200180610d9c6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610944908490610b53565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b610b65826001600160a01b0316610d35565b610bb6576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310610bf45780518252601f199092019160209182019101610bd5565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610c56576040519150601f19603f3d011682016040523d82523d6000602084013e610c5b565b606091505b509150915081610cb2576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610d0b57808060200190516020811015610cce57600080fd5b5051610d0b5760405162461bcd60e51b815260040180806020018281038252602a815260200180610d72602a913960400191505060405180910390fd5b50505050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610d6957508115155b94935050505056fe5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a7231582061d39987b8ceb84ad65ba3fbab46e239c29473a490e71cd6afb189eb9d46dbda64736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c80638119c065116100665780638119c065146100fa578063aea173d514610102578063c7af335214610128578063d27567f214610144578063d38bfff41461014c57610093565b80630c340a24146100985780631072cbea146100bc578063128a8b05146100ea5780635d36b190146100f2575b600080fd5b6100a0610172565b604080516001600160a01b039092168252519081900360200190f35b6100e8600480360360408110156100d257600080fd5b506001600160a01b038135169060200135610181565b005b6100a0610270565b6100e861027f565b6100e86102e1565b6100e86004803603602081101561011857600080fd5b50356001600160a01b03166106dc565b6101306107e9565b604080519115158252519081900360200190f35b6100a061080c565b6100e86004803603602081101561016257600080fd5b50356001600160a01b0316610824565b600061017c6108cd565b905090565b6101896107e9565b6101d7576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b7f53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac453580546002811415610241576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556102676102506108cd565b6001600160a01b038616908563ffffffff6108f216565b50600190555050565b6000546001600160a01b031681565b610287610949565b6001600160a01b0316336001600160a01b0316146102d65760405162461bcd60e51b8152600401808060200182810382526030815260200180610dd26030913960400191505060405180910390fd5b6102df3361096e565b565b73e75d77b1865ae93c7eaa3040b038d7aa7bc02f703314610349576040805162461bcd60e51b815260206004820152601760248201527f43616c6c6572206973206e6f7420746865205661756c74000000000000000000604482015290519081900360640190fd5b6000546001600160a01b031661035e576102df565b604080516370a0823160e01b81523060048201529051600091732a8e1e676ec238d8a992307b495b45b3feaa5e86916370a0823191602480820192602092909190829003018186803b1580156103b357600080fd5b505afa1580156103c7573d6000803e3d6000fd5b505050506040513d60208110156103dd57600080fd5b50519050683635c9adc5dea000008110156103f857506102df565b60408051600480825260a0820190925260609160208201608080388339019050509050732a8e1e676ec238d8a992307b495b45b3feaa5e868160008151811061043d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505073dac17f958d2ee523a2206206994597c13d831ec78160018151811061047f57fe5b6001600160a01b03928316602091820292909201810191909152600054604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b1580156104d357600080fd5b505afa1580156104e7573d6000803e3d6000fd5b505050506040513d60208110156104fd57600080fd5b505181518290600290811061050e57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050738207c1ffc5b6804f6024322ccf34f29c3541ae268160038151811061055057fe5b6001600160a01b03928316602091820292909201810191909152600080546040516338ed173960e01b815260048101878152602482018490523060648301819052426084840181905260a060448501908152895160a4860152895195909816976338ed1739978b97968b969495939460c4019187810191028083838b5b838110156105e55781810151838201526020016105cd565b505050509050019650505050505050600060405180830381600087803b15801561060e57600080fd5b505af1158015610622573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561064b57600080fd5b810190808051604051939291908464010000000082111561066b57600080fd5b90830190602082018581111561068057600080fd5b825186602082028301116401000000008211171561069d57600080fd5b82525081516020918201928201910280838360005b838110156106ca5781810151838201526020016106b2565b50505050905001604052505050505050565b6106e46107e9565b610732576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b600080546001600160a01b0319166001600160a01b038381169190911780835561077692732a8e1e676ec238d8a992307b495b45b3feaa5e86929190911690610a1c565b6000546107aa90732a8e1e676ec238d8a992307b495b45b3feaa5e86906001600160a01b031660001963ffffffff610a1c16565b604080516001600160a01b038316815290517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b60006107f36108cd565b6001600160a01b0316336001600160a01b031614905090565b73e75d77b1865ae93c7eaa3040b038d7aa7bc02f7081565b61082c6107e9565b61087a576040805162461bcd60e51b815260206004820152601a60248201527921b0b63632b91034b9903737ba103a34329023b7bb32b93737b960311b604482015290519081900360640190fd5b61088381610b2f565b806001600160a01b03166108956108cd565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610944908490610b53565b505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b0381166109c9576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b03166109db6108cd565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3610a1981610d11565b50565b801580610aa2575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015610a7457600080fd5b505afa158015610a88573d6000803e3d6000fd5b505050506040513d6020811015610a9e57600080fd5b5051155b610add5760405162461bcd60e51b8152600401808060200182810382526036815260200180610d9c6036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b179052610944908490610b53565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b610b65826001600160a01b0316610d35565b610bb6576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310610bf45780518252601f199092019160209182019101610bd5565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610c56576040519150601f19603f3d011682016040523d82523d6000602084013e610c5b565b606091505b509150915081610cb2576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610d0b57808060200190516020811015610cce57600080fd5b5051610d0b5760405162461bcd60e51b815260040180806020018281038252602a815260200180610d72602a913960400191505060405180910390fd5b50505050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590610d6957508115155b94935050505056fe5361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a7231582061d39987b8ceb84ad65ba3fbab46e239c29473a490e71cd6afb189eb9d46dbda64736f6c634300050b0032", + "devdoc": { + "methods": { + "claimGovernance()": { + "details": "Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor." + }, + "governor()": { + "details": "Returns the address of the current Governor." + }, + "isGovernor()": { + "details": "Returns true if the caller is the current Governor." + }, + "setUniswapAddr(address)": { + "details": "Set address of Uniswap for performing liquidation of strategy reward tokens. Setting to 0x0 will pause swaps.", + "params": { + "_address": "Address of Uniswap" + } + }, + "swap()": { + "details": "Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible protocol (e.g. Sushiswap)*" + }, + "transferGovernance(address)": { + "details": "Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete", + "params": { + "_newGovernor": "Address of the new Governor" + } + } + } + }, + "userdoc": { + "methods": { + "transferToken(address,uint256)": { + "notice": "Owner function to withdraw a specific amount of a token" + } + } + } +} \ No newline at end of file diff --git a/contracts/deployments/rinkeby/OracleRouter.json b/contracts/deployments/rinkeby/OracleRouter.json new file mode 100644 index 0000000000..ab8e7efdd7 --- /dev/null +++ b/contracts/deployments/rinkeby/OracleRouter.json @@ -0,0 +1,64 @@ +{ + "address": "0x3D69B41fDd3b8f555Feb3974086dA9790A2fccAb", + "abi": [ + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "price", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xd8903c3f9f19da96cf7550a6f31a037dd4d5534d663f7825ddd775a88c279be5", + "receipt": { + "to": null, + "from": "0xD85A569F3C26f81070544451131c742283360400", + "contractAddress": "0x3D69B41fDd3b8f555Feb3974086dA9790A2fccAb", + "transactionIndex": 2, + "gasUsed": "236798", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x72943011e618112023f24d8597b5a71a6031f46b8415888bdc8772efcf9a325d", + "transactionHash": "0xd8903c3f9f19da96cf7550a6f31a037dd4d5534d663f7825ddd775a88c279be5", + "logs": [], + "blockNumber": 8292741, + "cumulativeGasUsed": "274356", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "86605db9d81ca0a1790de251140fb0d9", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"price\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"methods\":{\"price(address)\":{\"params\":{\"asset\":\"address of the asset\"},\"return\":\"uint256 USD price of 1 of the asset, in 8 decimal fixed\"}}},\"userdoc\":{\"methods\":{\"price(address)\":{\"notice\":\"Returns the total price in 8 digit USD for a given asset.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/oracle/OracleRouter.sol\":\"OracleRouter\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IOracle {\\n /**\\n * @dev returns the asset price in USD, 8 decimal digits.\\n */\\n function price(address asset) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x7ddbe1f9ed76feb2fbd52ecfe449e17ef67f7edd5616c6a1eda92a84baa1190f\"},\"contracts/interfaces/chainlink/AggregatorV3Interface.sol\":{\"content\":\"pragma solidity ^0.5.11;\\n\\ninterface AggregatorV3Interface {\\n function decimals() external view returns (uint8);\\n\\n function description() external view returns (string memory);\\n\\n function version() external view returns (uint256);\\n\\n // getRoundData and latestRoundData should both raise \\\"No data present\\\"\\n // if they do not have data to report, instead of returning unset values\\n // which could be misinterpreted as actual reported values.\\n function getRoundData(uint80 _roundId)\\n external\\n view\\n returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n\\n function latestRoundData()\\n external\\n view\\n returns (\\n uint80 roundId,\\n int256 answer,\\n uint256 startedAt,\\n uint256 updatedAt,\\n uint80 answeredInRound\\n );\\n}\\n\",\"keccak256\":\"0xef73b8afeb1cf9a35e7f5d9cbc878eff44841f7a78a56a0aaafe9943c32848f7\"},\"contracts/oracle/OracleRouter.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport \\\"../interfaces/chainlink/AggregatorV3Interface.sol\\\";\\nimport { IOracle } from \\\"../interfaces/IOracle.sol\\\";\\n\\ncontract OracleRouterBase is IOracle {\\n uint256 constant MIN_DRIFT = uint256(70000000);\\n uint256 constant MAX_DRIFT = uint256(130000000);\\n\\n /**\\n * @dev The price feed contract to use for a particular asset.\\n * @param asset address of the asset\\n */\\n function feed(address asset) internal view returns (address);\\n\\n /**\\n * @notice Returns the total price in 8 digit USD for a given asset.\\n * @param asset address of the asset\\n * @return uint256 USD price of 1 of the asset, in 8 decimal fixed\\n */\\n function price(address asset) external view returns (uint256) {\\n address _feed = feed(asset);\\n require(_feed != address(0), \\\"Asset not available\\\");\\n (\\n uint80 roundID,\\n int256 _iprice,\\n uint256 startedAt,\\n uint256 timeStamp,\\n uint80 answeredInRound\\n ) = AggregatorV3Interface(_feed).latestRoundData();\\n uint256 _price = uint256(_iprice);\\n require(_price <= MAX_DRIFT, \\\"Oracle: Price exceeds max\\\");\\n require(_price >= MIN_DRIFT, \\\"Oracle: Price under min\\\");\\n return uint256(_price);\\n }\\n}\\n\\ncontract OracleRouter is OracleRouterBase {\\n /**\\n * @dev The price feed contract to use for a particular asset.\\n * @param asset address of the asset\\n */\\n function feed(address asset) internal view returns (address) {\\n // DAI\\n if (asset == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) {\\n return address(0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9);\\n // USDC\\n } else if (\\n asset == address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)\\n ) {\\n return address(0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6);\\n // USDT\\n } else if (\\n asset == address(0xdAC17F958D2ee523a2206206994597C13D831ec7)\\n ) {\\n return address(0x3E7d1eAB13ad0104d2750B8863b489D65364e32D);\\n } else {\\n require(false, \\\"Asset not available\\\");\\n }\\n }\\n}\\n\\ncontract OracleRouterDev is OracleRouterBase {\\n mapping(address => address) public assetToFeed;\\n\\n function setFeed(address _asset, address _feed) external {\\n assetToFeed[_asset] = _feed;\\n }\\n\\n /**\\n * @dev The price feed contract to use for a particular asset.\\n * @param asset address of the asset\\n */\\n function feed(address asset) internal view returns (address) {\\n return assetToFeed[asset];\\n }\\n}\\n\",\"keccak256\":\"0xfb59c9ffec329bad84bb4e7d56b8688472afa4523ec4f93bce3033314a2694ff\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610352806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063aea9107814610030575b600080fd5b6100566004803603602081101561004657600080fd5b50356001600160a01b0316610068565b60408051918252519081900360200190f35b60008061007483610218565b90506001600160a01b0381166100c7576040805162461bcd60e51b81526020600482015260136024820152724173736574206e6f7420617661696c61626c6560681b604482015290519081900360640190fd5b6000806000806000856001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561010857600080fd5b505afa15801561011c573d6000803e3d6000fd5b505050506040513d60a081101561013257600080fd5b50805160208201516040830151606084015160809094015192985090965094509092509050836307bfa4808111156101b1576040805162461bcd60e51b815260206004820152601960248201527f4f7261636c653a2050726963652065786365656473206d617800000000000000604482015290519081900360640190fd5b63042c1d8081101561020a576040805162461bcd60e51b815260206004820152601760248201527f4f7261636c653a20507269636520756e646572206d696e000000000000000000604482015290519081900360640190fd5b96505050505050505b919050565b60006001600160a01b038216736b175474e89094c44da98b954eedeac495271d0f141561025a575073aed0c38402a5d19df6e4c03f4e2dced6e29c1ee9610213565b6001600160a01b03821673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48141561029a5750738fffffd4afb6115b954bd326cbe7b4ba576818f6610213565b6001600160a01b03821673dac17f958d2ee523a2206206994597c13d831ec714156102da5750733e7d1eab13ad0104d2750b8863b489d65364e32d610213565b6040805162461bcd60e51b81526020600482015260136024820152724173736574206e6f7420617661696c61626c6560681b604482015290519081900360640190fdfea265627a7a723158205a0faac8e8f1032354adde1b81703c6f8f40f7764602d0c554c7ca614fb302ca64736f6c634300050b0032", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063aea9107814610030575b600080fd5b6100566004803603602081101561004657600080fd5b50356001600160a01b0316610068565b60408051918252519081900360200190f35b60008061007483610218565b90506001600160a01b0381166100c7576040805162461bcd60e51b81526020600482015260136024820152724173736574206e6f7420617661696c61626c6560681b604482015290519081900360640190fd5b6000806000806000856001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561010857600080fd5b505afa15801561011c573d6000803e3d6000fd5b505050506040513d60a081101561013257600080fd5b50805160208201516040830151606084015160809094015192985090965094509092509050836307bfa4808111156101b1576040805162461bcd60e51b815260206004820152601960248201527f4f7261636c653a2050726963652065786365656473206d617800000000000000604482015290519081900360640190fd5b63042c1d8081101561020a576040805162461bcd60e51b815260206004820152601760248201527f4f7261636c653a20507269636520756e646572206d696e000000000000000000604482015290519081900360640190fd5b96505050505050505b919050565b60006001600160a01b038216736b175474e89094c44da98b954eedeac495271d0f141561025a575073aed0c38402a5d19df6e4c03f4e2dced6e29c1ee9610213565b6001600160a01b03821673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48141561029a5750738fffffd4afb6115b954bd326cbe7b4ba576818f6610213565b6001600160a01b03821673dac17f958d2ee523a2206206994597c13d831ec714156102da5750733e7d1eab13ad0104d2750b8863b489d65364e32d610213565b6040805162461bcd60e51b81526020600482015260136024820152724173736574206e6f7420617661696c61626c6560681b604482015290519081900360640190fdfea265627a7a723158205a0faac8e8f1032354adde1b81703c6f8f40f7764602d0c554c7ca614fb302ca64736f6c634300050b0032", + "devdoc": { + "methods": { + "price(address)": { + "params": { + "asset": "address of the asset" + }, + "return": "uint256 USD price of 1 of the asset, in 8 decimal fixed" + } + } + }, + "userdoc": { + "methods": { + "price(address)": { + "notice": "Returns the total price in 8 digit USD for a given asset." + } + } + } +} \ No newline at end of file diff --git a/contracts/deployments/rinkeby/VaultAdmin.json b/contracts/deployments/rinkeby/VaultAdmin.json index 6f1c3d1bdc..a725b55e09 100644 --- a/contracts/deployments/rinkeby/VaultAdmin.json +++ b/contracts/deployments/rinkeby/VaultAdmin.json @@ -1,5 +1,5 @@ { - "address": "0x7ebBc1eaF5843703F19DF5754334870DA8bc8491", + "address": "0x93662b49b557b08049ffc8Ebdd852bD8DB04FfCe", "abi": [ { "constant": false, @@ -96,6 +96,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDMint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -156,27 +177,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDRedeem", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": false, "inputs": [ @@ -317,8 +317,14 @@ }, { "constant": false, - "inputs": [], - "name": "claimGovernance", + "inputs": [ + { + "internalType": "address", + "name": "_strategyAddr", + "type": "address" + } + ], + "name": "withdrawAllFromStrategy", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -326,38 +332,26 @@ }, { "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_maxSupplyDiff", - "type": "uint256" - } - ], - "name": "setMaxSupplyDiff", + "inputs": [], + "name": "claimGovernance", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDMint", - "outputs": [ { "internalType": "uint256", - "name": "", + "name": "_maxSupplyDiff", "type": "uint256" } ], + "name": "setMaxSupplyDiff", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -405,6 +399,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -584,6 +599,15 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [], + "name": "withdrawAllFromStrategies", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -958,42 +982,42 @@ "type": "event" } ], - "transactionHash": "0x3ecda2c634fe01420c3b45012020f3f899bd4145a2ca3bcd267c17fed8d5a62b", + "transactionHash": "0x37cc1fc124a396a1c8fa94726cfd19c7122bcc1062ae95d1ae078895415f5d8e", "receipt": { "to": null, "from": "0xD85A569F3C26f81070544451131c742283360400", - "contractAddress": "0x7ebBc1eaF5843703F19DF5754334870DA8bc8491", - "transactionIndex": 3, - "gasUsed": "2698492", - "logsBloom": "0x00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000800800000000000000000000000000000000000004000000000000000000000000008000000000000000000000000000000000000400000000000000000000000000000000020000000000000000000000000000000000000000000010000000000000000000000000000000000000000020000000000000000000000000000000000000000400000000000000000000000000", - "blockHash": "0x355115c9d70706f940b9620aea409f939b004554fcb6fc1afaefafb6119d9129", - "transactionHash": "0x3ecda2c634fe01420c3b45012020f3f899bd4145a2ca3bcd267c17fed8d5a62b", + "contractAddress": "0x93662b49b557b08049ffc8Ebdd852bD8DB04FfCe", + "transactionIndex": 2, + "gasUsed": "2799997", + "logsBloom": "0x00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000200000000000000000000000000000002000000010000000000000000000000000000000000000000020000000000000000000000000000000000000000400000000000000000000000000", + "blockHash": "0xf33d927045d780c5898e76edc8dc9dac4ed25cd4e9114b64e2c5d1607b1ebac2", + "transactionHash": "0x37cc1fc124a396a1c8fa94726cfd19c7122bcc1062ae95d1ae078895415f5d8e", "logs": [ { - "transactionIndex": 3, - "blockNumber": 8051332, - "transactionHash": "0x3ecda2c634fe01420c3b45012020f3f899bd4145a2ca3bcd267c17fed8d5a62b", - "address": "0x7ebBc1eaF5843703F19DF5754334870DA8bc8491", + "transactionIndex": 2, + "blockNumber": 8292732, + "transactionHash": "0x37cc1fc124a396a1c8fa94726cfd19c7122bcc1062ae95d1ae078895415f5d8e", + "address": "0x93662b49b557b08049ffc8Ebdd852bD8DB04FfCe", "topics": [ "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000d85a569f3c26f81070544451131c742283360400" ], "data": "0x", - "logIndex": 9, - "blockHash": "0x355115c9d70706f940b9620aea409f939b004554fcb6fc1afaefafb6119d9129" + "logIndex": 8, + "blockHash": "0xf33d927045d780c5898e76edc8dc9dac4ed25cd4e9114b64e2c5d1607b1ebac2" } ], - "blockNumber": 8051332, - "cumulativeGasUsed": "2942768", + "blockNumber": 8292732, + "cumulativeGasUsed": "3127329", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "9fed08ce0928345e8230635be8b09173", - "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":false,\"inputs\":[],\"name\":\"unpauseRebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"redeemFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"setTrusteeFeeBps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyAddr\",\"type\":\"address\"}],\"name\":\"harvest\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"transferToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"removeStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultBuffer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"}],\"name\":\"priceUSDRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setTrusteeAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"setPriceProvider\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"approveStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pauseCapital\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"harvest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"supportAsset\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebaseThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"setMaxSupplyDiff\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"string\",\"name\":\"symbol\",\"type\":\"string\"}],\"name\":\"priceUSDMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setStrategistAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyFromAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategyToAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_assets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"}],\"name\":\"reallocate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxSupplyDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"setVaultBuffer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpauseCapital\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoAllocateThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetDefaultStrategies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setUniswapAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"setAutoAllocateThreshold\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"priceProvider\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"setRebaseThreshold\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"setAssetDefaultStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pauseRebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"capitalPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"setRedeemFeeBps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImpl\",\"type\":\"address\"}],\"name\":\"setAdminImpl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"AssetSupported\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"AssetDefaultStrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebasePaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebaseUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"VaultBufferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"RedeemFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"PriceProviderUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"AllocateThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"RebaseThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyDiffChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_yield\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"YieldDistribution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"TrusteeFeeBpsChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"TrusteeAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"approveStrategy(address)\":{\"details\":\"Add a strategy to the Vault.\",\"params\":{\"_addr\":\"Address of the strategy to add\"}},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"harvest()\":{\"details\":\"Collect reward tokens from all strategies and swap for supported stablecoin via Uniswap\"},\"harvest(address)\":{\"details\":\"Collect reward tokens for a specific strategy and swap for supported stablecoin via Uniswap. Called from the vault.\",\"params\":{\"_strategyAddr\":\"Address of the strategy to collect rewards from\"}},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"pauseCapital()\":{\"details\":\"Set the deposit paused flag to true to prevent capital movement.\"},\"pauseRebase()\":{\"details\":\"Set the deposit paused flag to true to prevent rebasing.\"},\"priceUSDMint(string)\":{\"details\":\"Returns the total price in 18 digit USD for a given asset. Using Min since min is what we use for mint pricing\",\"params\":{\"symbol\":\"String symbol of the asset\"},\"return\":\"uint256 USD price of 1 of the asset\"},\"priceUSDRedeem(string)\":{\"details\":\"Returns the total price in 18 digit USD for a given asset. Using Max since max is what we use for redeem pricing\",\"params\":{\"symbol\":\"String symbol of the asset\"},\"return\":\"uint256 USD price of 1 of the asset\"},\"reallocate(address,address,address[],uint256[])\":{\"params\":{\"_amounts\":\"Array of amounts of each corresponding asset to move.\",\"_assets\":\"Array of asset address that will be moved\",\"_strategyFromAddress\":\"Address of Strategy to move assets from.\",\"_strategyToAddress\":\"Address of Strategy to move assets to.\"}},\"removeStrategy(address)\":{\"details\":\"Remove a strategy from the Vault. Removes all invested assets and returns them to the Vault.\",\"params\":{\"_addr\":\"Address of the strategy to remove\"}},\"setAdminImpl(address)\":{\"details\":\"set the implementation for the admin, this needs to be in a base class else we cannot set it\",\"params\":{\"newImpl\":\"address of the implementation\"}},\"setAssetDefaultStrategy(address,address)\":{\"details\":\"Set the default Strategy for an asset, i.e. the one which the asset will be automatically allocated to and withdrawn from\",\"params\":{\"_asset\":\"Address of the asset\",\"_strategy\":\"Address of the Strategy\"}},\"setAutoAllocateThreshold(uint256)\":{\"details\":\"Sets the minimum amount of OUSD in a mint to trigger an automatic allocation of funds afterwords.\",\"params\":{\"_threshold\":\"OUSD amount with 18 fixed decimals.\"}},\"setMaxSupplyDiff(uint256)\":{\"details\":\"Sets the maximum allowable difference between total supply and backing assets' value.\"},\"setPriceProvider(address)\":{\"details\":\"Set address of price provider.\",\"params\":{\"_priceProvider\":\"Address of price provider\"}},\"setRebaseThreshold(uint256)\":{\"details\":\"Set a minimum amount of OUSD in a mint or redeem that triggers a rebase\",\"params\":{\"_threshold\":\"OUSD amount with 18 fixed decimals.\"}},\"setRedeemFeeBps(uint256)\":{\"details\":\"Set a fee in basis points to be charged for a redeem.\",\"params\":{\"_redeemFeeBps\":\"Basis point fee to be charged\"}},\"setStrategistAddr(address)\":{\"details\":\"Set address of Strategist\",\"params\":{\"_address\":\"Address of Strategist\"}},\"setTrusteeAddress(address)\":{\"details\":\"Sets the trusteeAddress that can receive a portion of yield. Setting to the zero address disables this feature.\"},\"setTrusteeFeeBps(uint256)\":{\"details\":\"Sets the TrusteeFeeBps to the percentage of yield that should be received in basis points.\"},\"setUniswapAddr(address)\":{\"details\":\"Set address of Uniswap for performing liquidation of strategy reward tokens\",\"params\":{\"_address\":\"Address of Uniswap\"}},\"setVaultBuffer(uint256)\":{\"details\":\"Set a buffer of assets to keep in the Vault to handle most redemptions without needing to spend gas unwinding assets from a Strategy.\",\"params\":{\"_vaultBuffer\":\"Percentage using 18 decimals. 100% = 1e18.\"}},\"supportAsset(address)\":{\"details\":\"Add a supported asset to the contract, i.e. one that can be to mint OUSD.\",\"params\":{\"_asset\":\"Address of asset\"}},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}},\"transferToken(address,uint256)\":{\"details\":\"Transfer token to governor. Intended for recovering tokens stuck in contract, i.e. mistaken sends.\",\"params\":{\"_amount\":\"Amount of the asset to transfer\",\"_asset\":\"Address for the asset\"}},\"unpauseCapital()\":{\"details\":\"Set the deposit paused flag to false to enable capital movement.\"},\"unpauseRebase()\":{\"details\":\"Set the deposit paused flag to true to allow rebasing.\"}}},\"userdoc\":{\"methods\":{\"reallocate(address,address,address[],uint256[])\":{\"notice\":\"Move assets from one Strategy to another\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/vault/VaultAdmin.sol\":\"VaultAdmin\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"@openzeppelin/upgrades/contracts/Initializable.sol\":{\"content\":\"pragma solidity >=0.4.24 <0.7.0;\\n\\n\\n/**\\n * @title Initializable\\n *\\n * @dev Helper contract to support initializer functions. To use it, replace\\n * the constructor with a function that has the `initializer` modifier.\\n * WARNING: Unlike constructors, initializer functions must be manually\\n * invoked. This applies both to deploying an Initializable contract, as well\\n * as extending an Initializable contract via inheritance.\\n * WARNING: When used with inheritance, manual care must be taken to not invoke\\n * a parent initializer twice, or ensure that all initializers are idempotent,\\n * because this is not dealt with automatically as with constructors.\\n */\\ncontract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to use in the initializer function of a contract.\\n */\\n modifier initializer() {\\n require(initializing || isConstructor() || !initialized, \\\"Contract instance has already been initialized\\\");\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function isConstructor() private view returns (bool) {\\n // extcodesize checks the size of the code stored in an address, and\\n // address returns the current address. Since the code is still not\\n // deployed when running a constructor, any checks on its code size will\\n // yield zero, making it an effective way to detect if a contract is\\n // under construction or not.\\n address self = address(this);\\n uint256 cs;\\n assembly { cs := extcodesize(self) }\\n return cs == 0;\\n }\\n\\n // Reserved storage space to allow for layout changes in the future.\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x9bfec92e36234ecc99b5d37230acb6cd1f99560233753162204104a4897e8721\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x01eab42b6d54fa5389598e0663c24680ecc017e2da848e8ea1c40aeaa8225eef\"},\"contracts/interfaces/IMinMaxOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IMinMaxOracle {\\n //Assuming 8 decimals\\n function priceMin(string calldata symbol) external view returns (uint256);\\n\\n function priceMax(string calldata symbol) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x164c8759ca5a8e39bbe1de6b2504098c543b2f15663c9d452e083418f8313f48\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to platform\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Deposit the entire balance of all supported assets in the Strategy\\n * to the platform\\n */\\n function depositAll() external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardToken() external;\\n\\n /**\\n * @dev The address of the reward token for the Strategy.\\n */\\n function rewardTokenAddress() external pure returns (address);\\n\\n /**\\n * @dev The threshold (denominated in the reward token) over which the\\n * vault will auto harvest on allocate calls.\\n */\\n function rewardLiquidationThreshold() external pure returns (uint256);\\n}\\n\",\"keccak256\":\"0xe03dc1c97ad3677296da9a7e1e5f708abd227d1147f6f220c5cc8f23c1cd87e0\"},\"contracts/interfaces/uniswap/IUniswapV2Router02.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IUniswapV2Router {\\n function WETH() external pure returns (address);\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address[] calldata path,\\n address to,\\n uint256 deadline\\n ) external returns (uint256[] memory amounts);\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n );\\n}\\n\",\"keccak256\":\"0x33943cfab99996faa745df3c21b95b3ed49783b4c3392e4c71e25f6712af509b\"},\"contracts/token/OUSD.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {\\n InitializableERC20Detailed\\n} from \\\"../utils/InitializableERC20Detailed.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\n/**\\n * NOTE that this is an ERC20 token but the invariant that the sum of\\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\\n * rebasing design. Any integrations with OUSD should be aware.\\n */\\n\\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n\\n event TotalSupplyUpdated(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n\\n enum RebaseOptions { NotSet, OptOut, OptIn }\\n\\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\\n uint256 public _totalSupply;\\n mapping(address => mapping(address => uint256)) private _allowances;\\n address public vaultAddress = address(0);\\n mapping(address => uint256) private _creditBalances;\\n uint256 public rebasingCredits;\\n uint256 public rebasingCreditsPerToken;\\n // Frozen address/credits are non rebasing (value is held in contracts which\\n // do not receive yield unless they explicitly opt in)\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) public nonRebasingCreditsPerToken;\\n mapping(address => RebaseOptions) public rebaseState;\\n\\n function initialize(\\n string calldata _nameArg,\\n string calldata _symbolArg,\\n address _vaultAddress\\n ) external onlyGovernor initializer {\\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\\n rebasingCreditsPerToken = 1e18;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Savings Manager contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return The total supply of OUSD.\\n */\\n function totalSupply() public view returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the _amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n if (_creditBalances[_account] == 0) return 0;\\n return\\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n return (_creditBalances[_account], _creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the _amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(\\n _value <= balanceOf(msg.sender),\\n \\\"Transfer greater than balance\\\"\\n );\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The _amount of tokens to be transferred.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(_value <= balanceOf(_from), \\\"Transfer greater than balance\\\");\\n\\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\\n _value\\n );\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Update the count of non rebasing credits in response to a transfer\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value Amount of OUSD to transfer\\n */\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\\n\\n // Credits deducted and credited might be different due to the\\n // differing creditsPerToken used by each account\\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\\n\\n _creditBalances[_from] = _creditBalances[_from].sub(\\n creditsDeducted,\\n \\\"Transfer amount exceeds balance\\\"\\n );\\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\\n\\n if (isNonRebasingTo && !isNonRebasingFrom) {\\n // Transfer to non-rebasing account from rebasing account, credits\\n // are removed from the non rebasing tally\\n nonRebasingSupply = nonRebasingSupply.add(_value);\\n // Update rebasingCredits by subtracting the deducted amount\\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\\n // Transfer to rebasing account from non-rebasing account\\n // Decreasing non-rebasing credits by the amount that was sent\\n nonRebasingSupply = nonRebasingSupply.sub(_value);\\n // Update rebasingCredits by adding the credited amount\\n rebasingCredits = rebasingCredits.add(creditsCredited);\\n }\\n }\\n\\n /**\\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n public\\n view\\n returns (uint256)\\n {\\n return _allowances[_owner][_spender];\\n }\\n\\n /**\\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\\n * msg.sender. This method is included for ERC20 compatibility.\\n * increaseAllowance and decreaseAllowance should be used instead.\\n * Changing an allowance with this method brings the risk that someone may transfer both\\n * the old and the new allowance - if they are both greater than zero - if a transfer\\n * transaction is mined before the later approve() call is mined.\\n *\\n * @param _spender The address which will spend the funds.\\n * @param _value The _amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) public returns (bool) {\\n _allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\\n * This method should be used instead of approve() to avoid the double approval vulnerability\\n * described above.\\n * @param _spender The address which will spend the funds.\\n * @param _addedValue The _amount of tokens to increase the allowance by.\\n */\\n function increaseAllowance(address _spender, uint256 _addedValue)\\n public\\n returns (bool)\\n {\\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\\n .add(_addedValue);\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\\n * @param _spender The address which will spend the funds.\\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\\n */\\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\\n public\\n returns (bool)\\n {\\n uint256 oldValue = _allowances[msg.sender][_spender];\\n if (_subtractedValue >= oldValue) {\\n _allowances[msg.sender][_spender] = 0;\\n } else {\\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\\n }\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Mints new tokens, increasing totalSupply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n _mint(_account, _amount);\\n }\\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 * - `to` cannot be the zero address.\\n */\\n function _mint(address _account, uint256 _amount) internal nonReentrant {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\\n\\n // If the account is non rebasing and doesn't have a set creditsPerToken\\n // then set it i.e. this is a mint from a fresh contract\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.add(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.add(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.add(_amount);\\n\\n require(_totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @dev Burns tokens, decreasing totalSupply.\\n */\\n function burn(address account, uint256 amount) external onlyVault {\\n _burn(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 nonReentrant {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n uint256 currentCredits = _creditBalances[_account];\\n\\n // Remove the credits, burning rounding errors\\n if (\\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\\n ) {\\n // Handle dust from rounding\\n _creditBalances[_account] = 0;\\n } else if (currentCredits > creditAmount) {\\n _creditBalances[_account] = _creditBalances[_account].sub(\\n creditAmount\\n );\\n } else {\\n revert(\\\"Remove exceeds balance\\\");\\n }\\n\\n // Remove from the credit tallies and non-rebasing supply\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.sub(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.sub(_amount);\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n if (nonRebasingCreditsPerToken[_account] != 0) {\\n return nonRebasingCreditsPerToken[_account];\\n } else {\\n return rebasingCreditsPerToken;\\n }\\n }\\n\\n /**\\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\\n * Also, ensure contracts are non-rebasing if they have not opted in.\\n * @param _account Address of the account.\\n */\\n function _isNonRebasingAccount(address _account) internal returns (bool) {\\n bool isContract = Address.isContract(_account);\\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\\n _ensureRebasingMigration(_account);\\n }\\n return nonRebasingCreditsPerToken[_account] > 0;\\n }\\n\\n /**\\n * @dev Ensures internal account for rebasing and non-rebasing credits and\\n * supply is updated following deployment of frozen yield change.\\n */\\n function _ensureRebasingMigration(address _account) internal {\\n if (nonRebasingCreditsPerToken[_account] == 0) {\\n // Set fixed credits per token for this account\\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\\n // Update non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\\n // Update credit tallies\\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\\n }\\n }\\n\\n /**\\n * @dev Add a contract address to the non rebasing exception list. I.e. the\\n * address's balance will be part of rebases so the account will be exposed\\n * to upside and downside.\\n */\\n function rebaseOptIn() public nonReentrant {\\n require(_isNonRebasingAccount(msg.sender), \\\"Account has not opted out\\\");\\n\\n // Convert balance into the same amount at the current exchange rate\\n uint256 newCreditBalance = _creditBalances[msg.sender]\\n .mul(rebasingCreditsPerToken)\\n .div(_creditsPerToken(msg.sender));\\n\\n // Decreasing non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\\n\\n _creditBalances[msg.sender] = newCreditBalance;\\n\\n // Increase rebasing credits, totalSupply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\\n\\n rebaseState[msg.sender] = RebaseOptions.OptIn;\\n\\n // Delete any fixed credits per token\\n delete nonRebasingCreditsPerToken[msg.sender];\\n }\\n\\n /**\\n * @dev Remove a contract address to the non rebasing exception list.\\n */\\n function rebaseOptOut() public nonReentrant {\\n require(!_isNonRebasingAccount(msg.sender), \\\"Account has not opted in\\\");\\n\\n // Increase non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\\n // Set fixed credits per token\\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\\n\\n // Decrease rebasing credits, total supply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\\n\\n // Mark explicitly opted out of rebasing\\n rebaseState[msg.sender] = RebaseOptions.OptOut;\\n }\\n\\n /**\\n * @dev Modify the supply without minting new tokens. This uses a change in\\n * the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n * @return uint256 representing the new total supply.\\n */\\n function changeSupply(uint256 _newTotalSupply)\\n external\\n onlyVault\\n nonReentrant\\n {\\n require(_totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (_totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n return;\\n }\\n\\n _totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\\n _totalSupply.sub(nonRebasingSupply)\\n );\\n\\n require(rebasingCreditsPerToken > 0, \\\"Invalid change in supply\\\");\\n\\n _totalSupply = rebasingCredits\\n .divPrecisely(rebasingCreditsPerToken)\\n .add(nonRebasingSupply);\\n\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n }\\n}\\n\",\"keccak256\":\"0xea89a8b152b363982ba8db340b1e20c3194b2e75a06630cbbf43e3c50fff61a4\"},\"contracts/utils/Helpers.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0xd2ca92e0af883dc1aec5b22caced274e59829e0e30a9e955dcc48b8d921f5cdc\"},\"contracts/utils/InitializableERC20Detailed.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/**\\n * @dev Optional functions from the ERC20 standard.\\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\\n */\\ncontract InitializableERC20Detailed is IERC20 {\\n // Storage gap to skip storage from prior to OUSD reset\\n uint256[100] private _____gap;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\\n * these values are immutable: they can only be set once during\\n * construction.\\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\\n */\\n function _initialize(\\n string memory nameArg,\\n string memory symbolArg,\\n uint8 decimalsArg\\n ) internal {\\n _name = nameArg;\\n _symbol = symbolArg;\\n _decimals = decimalsArg;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view 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 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.\\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 returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x7919369d0f3bd74b4f0ee78a682afe43f91b186cdd0708e303068e4feeb29007\"},\"contracts/utils/StableMath.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n// Based on StableMath from Stability Labs Pty. Ltd.\\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\\n\\nlibrary StableMath {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Scaling unit for use in specific calculations,\\n * where 1 * 10**18, or 1e18 represents a unit '1'\\n */\\n uint256 private constant FULL_SCALE = 1e18;\\n\\n /***************************************\\n Helpers\\n ****************************************/\\n\\n /**\\n * @dev Adjust the scale of an integer\\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\\n */\\n function scaleBy(uint256 x, int8 adjustment)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (adjustment > 0) {\\n x = x.mul(10**uint256(adjustment));\\n } else if (adjustment < 0) {\\n x = x.div(10**uint256(adjustment * -1));\\n }\\n return x;\\n }\\n\\n /***************************************\\n Precise Arithmetic\\n ****************************************/\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\\n return mulTruncateScale(x, y, FULL_SCALE);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @param scale Scale unit\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncateScale(\\n uint256 x,\\n uint256 y,\\n uint256 scale\\n ) internal pure returns (uint256) {\\n // e.g. assume scale = fullScale\\n // z = 10e18 * 9e17 = 9e36\\n uint256 z = x.mul(y);\\n // return 9e38 / 1e18 = 9e18\\n return z.div(scale);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit, rounded up to the closest base unit.\\n */\\n function mulTruncateCeil(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e17 * 17268172638 = 138145381104e17\\n uint256 scaled = x.mul(y);\\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\\n return ceil.div(FULL_SCALE);\\n }\\n\\n /**\\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\\n * @param x Left hand input to division\\n * @param y Right hand input to division\\n * @return Result after multiplying the left operand by the scale, and\\n * executing the division on the right hand input.\\n */\\n function divPrecisely(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e18 * 1e18 = 8e36\\n uint256 z = x.mul(FULL_SCALE);\\n // e.g. 8e36 / 10e18 = 8e17\\n return z.div(y);\\n }\\n}\\n\",\"keccak256\":\"0xa77fccf850feb6d54ba3a6530f92554caef8a67a1ceb573d4f8a5d1bf64ff9d2\"},\"contracts/vault/VaultAdmin.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Vault Admin Contract\\n * @notice The VaultAdmin contract makes configuration and admin calls on the vault.\\n * @author Origin Protocol Inc\\n */\\n\\nimport \\\"./VaultStorage.sol\\\";\\nimport { IMinMaxOracle } from \\\"../interfaces/IMinMaxOracle.sol\\\";\\nimport { IUniswapV2Router } from \\\"../interfaces/uniswap/IUniswapV2Router02.sol\\\";\\n\\ncontract VaultAdmin is VaultStorage {\\n /**\\n * @dev Verifies that the caller is the Vault, Governor, or Strategist.\\n */\\n modifier onlyVaultOrGovernorOrStrategist() {\\n require(\\n msg.sender == address(this) ||\\n msg.sender == strategistAddr ||\\n isGovernor(),\\n \\\"Caller is not the Vault, Governor, or Strategist\\\"\\n );\\n _;\\n }\\n\\n modifier onlyGovernorOrStrategist() {\\n require(\\n msg.sender == strategistAddr || isGovernor(),\\n \\\"Caller is not the Strategist or Governor\\\"\\n );\\n _;\\n }\\n\\n /***************************************\\n Configuration\\n ****************************************/\\n\\n /**\\n * @dev Set address of price provider.\\n * @param _priceProvider Address of price provider\\n */\\n function setPriceProvider(address _priceProvider) external onlyGovernor {\\n priceProvider = _priceProvider;\\n emit PriceProviderUpdated(_priceProvider);\\n }\\n\\n /**\\n * @dev Set a fee in basis points to be charged for a redeem.\\n * @param _redeemFeeBps Basis point fee to be charged\\n */\\n function setRedeemFeeBps(uint256 _redeemFeeBps) external onlyGovernor {\\n redeemFeeBps = _redeemFeeBps;\\n emit RedeemFeeUpdated(_redeemFeeBps);\\n }\\n\\n /**\\n * @dev Set a buffer of assets to keep in the Vault to handle most\\n * redemptions without needing to spend gas unwinding assets from a Strategy.\\n * @param _vaultBuffer Percentage using 18 decimals. 100% = 1e18.\\n */\\n function setVaultBuffer(uint256 _vaultBuffer) external onlyGovernor {\\n require(_vaultBuffer <= 1e18, \\\"Invalid value\\\");\\n vaultBuffer = _vaultBuffer;\\n emit VaultBufferUpdated(_vaultBuffer);\\n }\\n\\n /**\\n * @dev Sets the minimum amount of OUSD in a mint to trigger an\\n * automatic allocation of funds afterwords.\\n * @param _threshold OUSD amount with 18 fixed decimals.\\n */\\n function setAutoAllocateThreshold(uint256 _threshold)\\n external\\n onlyGovernor\\n {\\n autoAllocateThreshold = _threshold;\\n emit AllocateThresholdUpdated(_threshold);\\n }\\n\\n /**\\n * @dev Set a minimum amount of OUSD in a mint or redeem that triggers a\\n * rebase\\n * @param _threshold OUSD amount with 18 fixed decimals.\\n */\\n function setRebaseThreshold(uint256 _threshold) external onlyGovernor {\\n rebaseThreshold = _threshold;\\n emit RebaseThresholdUpdated(_threshold);\\n }\\n\\n /**\\n * @dev Set address of Uniswap for performing liquidation of strategy reward\\n * tokens\\n * @param _address Address of Uniswap\\n */\\n function setUniswapAddr(address _address) external onlyGovernor {\\n uniswapAddr = _address;\\n emit UniswapUpdated(_address);\\n }\\n\\n /**\\n * @dev Set address of Strategist\\n * @param _address Address of Strategist\\n */\\n function setStrategistAddr(address _address) external onlyGovernor {\\n strategistAddr = _address;\\n emit StrategistUpdated(_address);\\n }\\n\\n /**\\n * @dev Set the default Strategy for an asset, i.e. the one which the asset\\n will be automatically allocated to and withdrawn from\\n * @param _asset Address of the asset\\n * @param _strategy Address of the Strategy\\n */\\n function setAssetDefaultStrategy(address _asset, address _strategy)\\n external\\n onlyGovernorOrStrategist\\n {\\n emit AssetDefaultStrategyUpdated(_asset, _strategy);\\n require(strategies[_strategy].isSupported, \\\"Strategy not approved\\\");\\n IStrategy strategy = IStrategy(_strategy);\\n require(assets[_asset].isSupported, \\\"Asset is not supported\\\");\\n require(\\n strategy.supportsAsset(_asset),\\n \\\"Asset not supported by Strategy\\\"\\n );\\n assetDefaultStrategies[_asset] = _strategy;\\n }\\n\\n /**\\n * @dev Add a supported asset to the contract, i.e. one that can be\\n * to mint OUSD.\\n * @param _asset Address of asset\\n */\\n function supportAsset(address _asset) external onlyGovernor {\\n require(!assets[_asset].isSupported, \\\"Asset already supported\\\");\\n\\n assets[_asset] = Asset({ isSupported: true });\\n allAssets.push(_asset);\\n\\n emit AssetSupported(_asset);\\n }\\n\\n /**\\n * @dev Add a strategy to the Vault.\\n * @param _addr Address of the strategy to add\\n */\\n function approveStrategy(address _addr) external onlyGovernor {\\n require(!strategies[_addr].isSupported, \\\"Strategy already approved\\\");\\n strategies[_addr] = Strategy({ isSupported: true, _deprecated: 0 });\\n allStrategies.push(_addr);\\n emit StrategyApproved(_addr);\\n }\\n\\n /**\\n * @dev Remove a strategy from the Vault. Removes all invested assets and\\n * returns them to the Vault.\\n * @param _addr Address of the strategy to remove\\n */\\n\\n function removeStrategy(address _addr) external onlyGovernor {\\n require(strategies[_addr].isSupported, \\\"Strategy not approved\\\");\\n\\n // Initialize strategyIndex with out of bounds result so function will\\n // revert if no valid index found\\n uint256 strategyIndex = allStrategies.length;\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n if (allStrategies[i] == _addr) {\\n strategyIndex = i;\\n break;\\n }\\n }\\n\\n if (strategyIndex < allStrategies.length) {\\n allStrategies[strategyIndex] = allStrategies[allStrategies.length -\\n 1];\\n allStrategies.pop();\\n\\n // Withdraw all assets\\n IStrategy strategy = IStrategy(_addr);\\n strategy.withdrawAll();\\n // Call harvest after withdraw in case withdraw triggers\\n // distribution of additional reward tokens (true for Compound)\\n _harvest(_addr);\\n emit StrategyRemoved(_addr);\\n }\\n\\n // Clean up struct in mapping, this can be removed later\\n // See https://github.com/OriginProtocol/origin-dollar/issues/324\\n strategies[_addr].isSupported = false;\\n }\\n\\n /**\\n * @notice Move assets from one Strategy to another\\n * @param _strategyFromAddress Address of Strategy to move assets from.\\n * @param _strategyToAddress Address of Strategy to move assets to.\\n * @param _assets Array of asset address that will be moved\\n * @param _amounts Array of amounts of each corresponding asset to move.\\n */\\n function reallocate(\\n address _strategyFromAddress,\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external onlyGovernorOrStrategist {\\n require(\\n strategies[_strategyFromAddress].isSupported,\\n \\\"Invalid from Strategy\\\"\\n );\\n require(\\n strategies[_strategyToAddress].isSupported,\\n \\\"Invalid to Strategy\\\"\\n );\\n require(_assets.length == _amounts.length, \\\"Parameter length mismatch\\\");\\n\\n IStrategy strategyFrom = IStrategy(_strategyFromAddress);\\n IStrategy strategyTo = IStrategy(_strategyToAddress);\\n\\n for (uint256 i = 0; i < _assets.length; i++) {\\n require(strategyTo.supportsAsset(_assets[i]), \\\"Asset unsupported\\\");\\n // Withdraw from Strategy and pass other Strategy as recipient\\n strategyFrom.withdraw(address(strategyTo), _assets[i], _amounts[i]);\\n }\\n // Tell new Strategy to deposit into protocol\\n strategyTo.depositAll();\\n }\\n\\n /**\\n * @dev Sets the maximum allowable difference between\\n * total supply and backing assets' value.\\n */\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor {\\n maxSupplyDiff = _maxSupplyDiff;\\n emit MaxSupplyDiffChanged(_maxSupplyDiff);\\n }\\n\\n /**\\n * @dev Sets the trusteeAddress that can receive a portion of yield.\\n * Setting to the zero address disables this feature.\\n */\\n function setTrusteeAddress(address _address) external onlyGovernor {\\n trusteeAddress = _address;\\n emit TrusteeAddressChanged(_address);\\n }\\n\\n /**\\n * @dev Sets the TrusteeFeeBps to the percentage of yield that should be\\n * received in basis points.\\n */\\n function setTrusteeFeeBps(uint256 _basis) external onlyGovernor {\\n require(_basis <= 5000, \\\"basis cannot exceed 50%\\\");\\n trusteeFeeBps = _basis;\\n emit TrusteeFeeBpsChanged(_basis);\\n }\\n\\n /***************************************\\n Pause\\n ****************************************/\\n\\n /**\\n * @dev Set the deposit paused flag to true to prevent rebasing.\\n */\\n function pauseRebase() external onlyGovernorOrStrategist {\\n rebasePaused = true;\\n emit RebasePaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to true to allow rebasing.\\n */\\n function unpauseRebase() external onlyGovernor {\\n rebasePaused = false;\\n emit RebaseUnpaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to true to prevent capital movement.\\n */\\n function pauseCapital() external onlyGovernorOrStrategist {\\n capitalPaused = true;\\n emit CapitalPaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to false to enable capital movement.\\n */\\n function unpauseCapital() external onlyGovernor {\\n capitalPaused = false;\\n emit CapitalUnpaused();\\n }\\n\\n /***************************************\\n Rewards\\n ****************************************/\\n\\n /**\\n * @dev Transfer token to governor. Intended for recovering tokens stuck in\\n * contract, i.e. mistaken sends.\\n * @param _asset Address for the asset\\n * @param _amount Amount of the asset to transfer\\n */\\n function transferToken(address _asset, uint256 _amount)\\n external\\n onlyGovernor\\n {\\n require(!assets[_asset].isSupported, \\\"Only unsupported assets\\\");\\n IERC20(_asset).safeTransfer(governor(), _amount);\\n }\\n\\n /**\\n * @dev Collect reward tokens from all strategies and swap for supported\\n * stablecoin via Uniswap\\n */\\n function harvest() external onlyGovernorOrStrategist {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n _harvest(allStrategies[i]);\\n }\\n }\\n\\n /**\\n * @dev Collect reward tokens for a specific strategy and swap for supported\\n * stablecoin via Uniswap. Called from the vault.\\n * @param _strategyAddr Address of the strategy to collect rewards from\\n */\\n function harvest(address _strategyAddr)\\n external\\n onlyVaultOrGovernorOrStrategist\\n returns (uint256[] memory)\\n {\\n return _harvest(_strategyAddr);\\n }\\n\\n /**\\n * @dev Collect reward tokens from a single strategy and swap them for a\\n * supported stablecoin via Uniswap\\n * @param _strategyAddr Address of the strategy to collect rewards from\\n */\\n function _harvest(address _strategyAddr)\\n internal\\n returns (uint256[] memory)\\n {\\n IStrategy strategy = IStrategy(_strategyAddr);\\n address rewardTokenAddress = strategy.rewardTokenAddress();\\n if (rewardTokenAddress != address(0)) {\\n strategy.collectRewardToken();\\n\\n if (uniswapAddr != address(0)) {\\n IERC20 rewardToken = IERC20(strategy.rewardTokenAddress());\\n uint256 rewardTokenAmount = rewardToken.balanceOf(\\n address(this)\\n );\\n if (rewardTokenAmount > 0) {\\n // Give Uniswap full amount allowance\\n rewardToken.safeApprove(uniswapAddr, 0);\\n rewardToken.safeApprove(uniswapAddr, rewardTokenAmount);\\n\\n // Uniswap redemption path\\n address[] memory path = new address[](3);\\n path[0] = strategy.rewardTokenAddress();\\n path[1] = IUniswapV2Router(uniswapAddr).WETH();\\n path[2] = allAssets[1]; // USDT\\n\\n return\\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\\n rewardTokenAmount,\\n uint256(0),\\n path,\\n address(this),\\n now.add(1800)\\n );\\n }\\n }\\n }\\n }\\n\\n /***************************************\\n Pricing\\n ****************************************/\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Using Min since min is what we use for mint pricing\\n * @param symbol String symbol of the asset\\n * @return uint256 USD price of 1 of the asset\\n */\\n function priceUSDMint(string calldata symbol)\\n external\\n view\\n returns (uint256)\\n {\\n return _priceUSDMint(symbol);\\n }\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Using Min since min is what we use for mint pricing\\n * @param symbol String symbol of the asset\\n * @return uint256 USD price of 1 of the asset\\n */\\n function _priceUSDMint(string memory symbol)\\n internal\\n view\\n returns (uint256)\\n {\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return IMinMaxOracle(priceProvider).priceMin(symbol).scaleBy(10);\\n }\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Using Max since max is what we use for redeem pricing\\n * @param symbol String symbol of the asset\\n * @return uint256 USD price of 1 of the asset\\n */\\n function priceUSDRedeem(string calldata symbol)\\n external\\n view\\n returns (uint256)\\n {\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return _priceUSDRedeem(symbol);\\n }\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Using Max since max is what we use for redeem pricing\\n * @param symbol String symbol of the asset\\n * @return uint256 USD price of 1 of the asset\\n */\\n function _priceUSDRedeem(string memory symbol)\\n internal\\n view\\n returns (uint256)\\n {\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return IMinMaxOracle(priceProvider).priceMax(symbol).scaleBy(10);\\n }\\n}\\n\",\"keccak256\":\"0x060d1e1f6e54a00e2b875274ebb432ffec38c5915e3bac54109f45fcb21070c2\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD VaultStorage Contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\n\\ncontract VaultStorage is Initializable, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n using SafeMath for int256;\\n using SafeERC20 for IERC20;\\n\\n event AssetSupported(address _asset);\\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\\n event PriceProviderUpdated(address _priceProvider);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event UniswapUpdated(address _address);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n\\n // Assets supported by the Vault, i.e. Stablecoins\\n struct Asset {\\n bool isSupported;\\n }\\n mapping(address => Asset) assets;\\n address[] allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n mapping(address => Strategy) strategies;\\n address[] allStrategies;\\n\\n // Address of the Oracle price provider contract\\n address public priceProvider;\\n // Pausing bools\\n bool public rebasePaused = false;\\n bool public capitalPaused = true;\\n // Redemption fee in basis points\\n uint256 public redeemFeeBps;\\n // Buffer of assets to keep in Vault to handle (most) withdrawals\\n uint256 public vaultBuffer;\\n // Mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n // Mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n OUSD oUSD;\\n\\n //keccak256(\\\"OUSD.vault.governor.admin.impl\\\");\\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\\n\\n // Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n // Address of Uniswap\\n address public uniswapAddr = address(0);\\n\\n // Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n // Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n mapping(address => address) public assetDefaultStrategies;\\n\\n uint256 public maxSupplyDiff;\\n\\n // Trustee address that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n // Amount of yield collected in basis points\\n uint256 public trusteeFeeBps;\\n\\n /**\\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\\n * @param newImpl address of the implementation\\n */\\n function setAdminImpl(address newImpl) external onlyGovernor {\\n require(\\n Address.isContract(newImpl),\\n \\\"new implementation is not a contract\\\"\\n );\\n bytes32 position = adminImplPosition;\\n assembly {\\n sstore(position, newImpl)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x02d224b70c086a3df5cf22792721aed5f278ddf4bc7b98b67ac9c38c767760a0\"}},\"version\":1}", - "bytecode": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b60008051602062002fdc83398151915255565b60008051602062002fdc8339815191525490565b612eea80620000f26000396000f3fe608060405234801561001057600080fd5b506004361061025e5760003560e01c80635d36b19011610146578063aea173d5116100c3578063c5f0084111610087578063c5f0084114610773578063c7af33521461077b578063d38bfff414610783578063e6cc5432146107a9578063eb03654b146107b1578063fc0cfeee146107ce5761025e565b8063aea173d5146106dd578063b2c9336d14610703578063b888879e14610720578063b890ebf614610728578063bc90106b146107455761025e565b80638e510b521161010a5780638e510b52146106825780638ec489a21461068a57806394828ffd146106a75780639fa1826e146106af578063a403e4d5146106b75761025e565b80635d36b190146104f2578063663e64ce146104fa578063686b37ca14610517578063773540b3146105855780637fe2d393146105ab5761025e565b806329a903ec116101df5780634641257d116101a35780634641257d1461049057806349c1d54d146104985780634cd55c2d146104a057806352d38e5d146104c657806353ca9f24146104ce578063570d8e1d146104ea5761025e565b806329a903ec146103a85780632da845a814610416578063372aa2241461043c5780633b8ae397146104625780633dbc911f146104885761025e565b80631072cbea116102265780631072cbea1461033e578063128a8b051461036a578063175188e8146103725780631edfe3da14610398578063207134b0146103a05761025e565b806309f49bf51461026357806309f6442c1461026d5780630acbda75146102875780630c340a24146102a45780630e5c011e146102c8575b600080fd5b61026b6107f4565b005b610275610873565b60408051918252519081900360200190f35b61026b6004803603602081101561029d57600080fd5b5035610879565b6102ac610952565b604080516001600160a01b039092168252519081900360200190f35b6102ee600480360360208110156102de57600080fd5b50356001600160a01b0316610961565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561032a578181015183820152602001610312565b505050509050019250505060405180910390f35b61026b6004803603604081101561035457600080fd5b506001600160a01b0381351690602001356109d5565b6102ac610ab0565b61026b6004803603602081101561038857600080fd5b50356001600160a01b0316610abf565b610275610d23565b610275610d29565b610275600480360360208110156103be57600080fd5b810190602081018135600160201b8111156103d857600080fd5b8201836020820111156103ea57600080fd5b803590602001918460018302840111600160201b8311171561040b57600080fd5b509092509050610d2f565b61026b6004803603602081101561042c57600080fd5b50356001600160a01b0316610d79565b61026b6004803603602081101561045257600080fd5b50356001600160a01b0316610e14565b61026b6004803603602081101561047857600080fd5b50356001600160a01b0316610eaf565b61026b61101c565b61026b6110b1565b6102ac61114b565b61026b600480360360208110156104b657600080fd5b50356001600160a01b031661115a565b6102756112b7565b6104d66112bd565b604080519115158252519081900360200190f35b6102ac6112cd565b61026b6112dc565b61026b6004803603602081101561051057600080fd5b503561133e565b6102756004803603602081101561052d57600080fd5b810190602081018135600160201b81111561054757600080fd5b82018360208201111561055957600080fd5b803590602001918460018302840111600160201b8311171561057a57600080fd5b5090925090506113c0565b61026b6004803603602081101561059b57600080fd5b50356001600160a01b0316611401565b61026b600480360360808110156105c157600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156105f457600080fd5b82018360208201111561060657600080fd5b803590602001918460208302840111600160201b8311171561062757600080fd5b919390929091602081019035600160201b81111561064457600080fd5b82018360208201111561065657600080fd5b803590602001918460208302840111600160201b8311171561067757600080fd5b50909250905061149c565b610275611827565b61026b600480360360208110156106a057600080fd5b503561182d565b61026b6118fc565b61027561197b565b6102ac600480360360208110156106cd57600080fd5b50356001600160a01b0316611981565b61026b600480360360208110156106f357600080fd5b50356001600160a01b031661199c565b61026b6004803603602081101561071957600080fd5b5035611a37565b6102ac611ab9565b61026b6004803603602081101561073e57600080fd5b5035611ac8565b61026b6004803603604081101561075b57600080fd5b506001600160a01b0381358116916020013516611b4a565b61026b611db5565b6104d6611e4a565b61026b6004803603602081101561079957600080fd5b50356001600160a01b0316611e6d565b6104d6611f07565b61026b600480360360208110156107c757600080fd5b5035611f17565b61026b600480360360208110156107e457600080fd5b50356001600160a01b0316611f99565b6107fc611e4a565b61083b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6037805460ff60a01b191690556040517fbc044409505c95b6b851433df96e1beae715c909d8e7c1d6d7ab783300d4e3b990600090a1565b60385481565b610881611e4a565b6108c0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611388811115610917576040805162461bcd60e51b815260206004820152601760248201527f62617369732063616e6e6f742065786365656420353025000000000000000000604482015290519081900360640190fd5b60438190556040805182815290517f56287a45051933ea374811b3d5d165033047be5572cac676f7c28b8be4f746c79181900360200190a150565b600061095c612048565b905090565b60603330148061097b5750603f546001600160a01b031633145b806109895750610989611e4a565b6109c45760405162461bcd60e51b8152600401808060200182810382526030815260200180612df66030913960400191505060405180910390fd5b6109cd8261206d565b90505b919050565b6109dd611e4a565b610a1c576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526033602052604090205460ff1615610a8a576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c7920756e737570706f7274656420617373657473000000000000000000604482015290519081900360640190fd5b610aac610a95610952565b6001600160a01b038416908363ffffffff6125ab16565b5050565b603e546001600160a01b031681565b610ac7611e4a565b610b06576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff16610b6b576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b60365460005b603654811015610bbd57826001600160a01b031660368281548110610b9257fe5b6000918252602090912001546001600160a01b03161415610bb557809150610bbd565b600101610b71565b50603654811015610d0157603680546000198101908110610bda57fe5b600091825260209091200154603680546001600160a01b039092169183908110610c0057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506036805480610c3957fe5b6001900381819060005260206000200160006101000a8154906001600160a01b03021916905590556000829050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ca157600080fd5b505af1158015610cb5573d6000803e3d6000fd5b50505050610cc28361206d565b50604080516001600160a01b038516815290517f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea49181900360200190a1505b506001600160a01b03166000908152603560205260409020805460ff19169055565b60395481565b60435481565b6000610d7083838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061260292505050565b90505b92915050565b610d81611e4a565b610dc0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1e4af5ac389e8cde1bdaa6830881b6c987c62a45cfb3b33d27d805cde3b577509181900360200190a150565b610e1c611e4a565b610e5b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603780546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb266add5f3044b17d27db796af992cecbe413921b4e8aaaee03c719e16b9806a9181900360200190a150565b610eb7611e4a565b610ef6576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff1615610f64576040805162461bcd60e51b815260206004820152601960248201527f537472617465677920616c726561647920617070726f76656400000000000000604482015290519081900360640190fd5b6040805180820182526001808252600060208084018281526001600160a01b038716808452603583528684209551865460ff19169015151786559051948401949094556036805493840181559091527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890910180546001600160a01b03191683179055825191825291517f960dd94cbb79169f09a4e445d58b895df2d9bffa5b31055d0932d801724a20d1929181900390910190a150565b603f546001600160a01b03163314806110385750611038611e4a565b6110735760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6037805460ff60a81b1916600160a81b1790556040517f71f0e5b62f846a22e0b4d159e516e62fa9c2b8eb570be15f83e67d98a2ee51e090600090a1565b603f546001600160a01b03163314806110cd57506110cd611e4a565b6111085760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b60005b6036548110156111485761113f6036828154811061112557fe5b6000918252602090912001546001600160a01b031661206d565b5060010161110b565b50565b6042546001600160a01b031681565b611162611e4a565b6111a1576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526033602052604090205460ff161561120f576040805162461bcd60e51b815260206004820152601760248201527f417373657420616c726561647920737570706f72746564000000000000000000604482015290519081900360640190fd5b604080516020808201835260018083526001600160a01b0385166000818152603384528581209451855460ff1916901515179094556034805492830181559093527f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c10180546001600160a01b03191683179055825191825291517f4f1ac48525e50059cc1cc6e0e1940ece0dd653a4db4841538d6aef036be2fb7b929181900390910190a150565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b6112e46126ef565b6001600160a01b0316336001600160a01b0316146113335760405162461bcd60e51b8152600401808060200182810382526030815260200180612e866030913960400191505060405180910390fd5b61133c33612714565b565b611346611e4a565b611385576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b60418190556040805182815290517f95201f9c21f26877223b1ff4073936a6484c35495649e60e55730497aeb60d939181900360200190a150565b6000610d7083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127bf92505050565b611409611e4a565b611448576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603f80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee9181900360200190a150565b603f546001600160a01b03163314806114b857506114b8611e4a565b6114f35760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6001600160a01b03861660009081526035602052604090205460ff16611558576040805162461bcd60e51b8152602060048201526015602482015274496e76616c69642066726f6d20537472617465677960581b604482015290519081900360640190fd5b6001600160a01b03851660009081526035602052604090205460ff166115bb576040805162461bcd60e51b8152602060048201526013602482015272496e76616c696420746f20537472617465677960681b604482015290519081900360640190fd5b82811461160f576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b858560005b858110156117c957816001600160a01b031663aa388af688888481811061163757fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561168d57600080fd5b505afa1580156116a1573d6000803e3d6000fd5b505050506040513d60208110156116b757600080fd5b50516116fe576040805162461bcd60e51b8152602060048201526011602482015270105cdcd95d081d5b9cdd5c1c1bdc9d1959607a1b604482015290519081900360640190fd5b826001600160a01b031663d9caed128389898581811061171a57fe5b905060200201356001600160a01b031688888681811061173657fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b1580156117a557600080fd5b505af11580156117b9573d6000803e3d6000fd5b5050600190920191506116149050565b50806001600160a01b031663de5f62686040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b505050505050505050505050565b60415481565b611835611e4a565b611874576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b670de0b6b3a76400008111156118c1576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015290519081900360640190fd5b60398190556040805182815290517f41ecb23a0e7865b25f38c268b7c3012220d822929e9edff07326e89d5bb822b59181900360200190a150565b611904611e4a565b611943576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6037805460ff60a81b191690556040517f891ebab18da80ebeeea06b1b1cede098329c4c008906a98370c2ac7a80b571cb90600090a1565b603a5481565b6040602081905260009182529020546001600160a01b031681565b6119a4611e4a565b6119e3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603e80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b611a3f611e4a565b611a7e576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603a8190556040805182815290517f2ec5fb5a3d2703edc461252d92ccd2799c3c74f01d97212b20388207fa17ae459181900360200190a150565b6037546001600160a01b031681565b611ad0611e4a565b611b0f576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603b8190556040805182815290517f39367850377ac04920a9a670f2180e7a94d83b15ad302e59875ec58fd10bd37d9181900360200190a150565b603f546001600160a01b0316331480611b665750611b66611e4a565b611ba15760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b604080516001600160a01b0380851682528316602082015281517fba58ce12801c949fa65f41c46ed108671c219baf945fa48d21026cea99ff252a929181900390910190a16001600160a01b03811660009081526035602052604090205460ff16611c4b576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260336020526040902054819060ff16611cb3576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b806001600160a01b031663aa388af6846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611d0957600080fd5b505afa158015611d1d573d6000803e3d6000fd5b505050506040513d6020811015611d3357600080fd5b5051611d86576040805162461bcd60e51b815260206004820152601f60248201527f4173736574206e6f7420737570706f7274656420627920537472617465677900604482015290519081900360640190fd5b506001600160a01b03918216600090815260406020819052902080546001600160a01b03191691909216179055565b603f546001600160a01b0316331480611dd15750611dd1611e4a565b611e0c5760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6037805460ff60a01b1916600160a01b1790556040517f8cff26a5985614b3d30629cc4ab83824bf115aec971b718d8f2f99562032e97290600090a1565b6000611e54612048565b6001600160a01b0316336001600160a01b031614905090565b611e75611e4a565b611eb4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611ebd81612827565b806001600160a01b0316611ecf612048565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b603754600160a81b900460ff1681565b611f1f611e4a565b611f5e576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b60388190556040805182815290517fd6c7508d6658ccee36b7b7d7fd72e5cbaeefb40c64eff24e9ae7470e846304ee9181900360200190a150565b611fa1611e4a565b611fe0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611fe98161284b565b6120245760405162461bcd60e51b8152600401808060200182810382526024815260200180612d696024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606060008290506000816001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156120af57600080fd5b505afa1580156120c3573d6000803e3d6000fd5b505050506040513d60208110156120d957600080fd5b505190506001600160a01b038116156125a457816001600160a01b0316630242241d6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561212757600080fd5b505af115801561213b573d6000803e3d6000fd5b5050603e546001600160a01b03161591506125a49050576000826001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b15801561218d57600080fd5b505afa1580156121a1573d6000803e3d6000fd5b505050506040513d60208110156121b757600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561220557600080fd5b505afa158015612219573d6000803e3d6000fd5b505050506040513d602081101561222f57600080fd5b5051905080156125a157603e5461225a906001600160a01b038481169116600063ffffffff61288716565b603e5461227a906001600160a01b0384811691168363ffffffff61288716565b60408051600380825260808201909252606091602082018380388339019050509050846001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156122d557600080fd5b505afa1580156122e9573d6000803e3d6000fd5b505050506040513d60208110156122ff57600080fd5b50518151829060009061230e57fe5b6001600160a01b03928316602091820292909201810191909152603e54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561236257600080fd5b505afa158015612376573d6000803e3d6000fd5b505050506040513d602081101561238c57600080fd5b505181518290600190811061239d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060346001815481106123cb57fe5b9060005260206000200160009054906101000a90046001600160a01b0316816002815181106123f657fe5b6001600160a01b039283166020918202929092010152603e54166338ed1739836000843061242c4261070863ffffffff61299a16565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b838110156124a557818101518382015260200161248d565b505050509050019650505050505050600060405180830381600087803b1580156124ce57600080fd5b505af11580156124e2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561250b57600080fd5b8101908080516040519392919084600160201b82111561252a57600080fd5b90830190602082018581111561253f57600080fd5b82518660208202830111600160201b8211171561255b57600080fd5b82525081516020918201928201910280838360005b83811015612588578181015183820152602001612570565b50505050905001604052505050955050505050506109d0565b50505b5050919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526125fd9084906129f4565b505050565b603754604051637bf0c21560e01b81526020600482018181528451602484015284516000946109cd94600a946001600160a01b0390921693637bf0c21593899391928392604490910191908501908083838d5b8381101561266d578181015183820152602001612655565b50505050905090810190601f16801561269a5780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b1580156126b757600080fd5b505afa1580156126cb573d6000803e3d6000fd5b505050506040513d60208110156126e157600080fd5b50519063ffffffff612bb216565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b03811661276f576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316612781612048565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a361114881612c0c565b60375460405163019af6bf60e41b81526020600482018181528451602484015284516000946109cd94600a946001600160a01b03909216936319af6bf093899391928392604490910191908501908083838d831561266d578181015183820152602001612655565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061287f57508115155b949350505050565b80158061290d575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156128df57600080fd5b505afa1580156128f3573d6000803e3d6000fd5b505050506040513d602081101561290957600080fd5b5051155b6129485760405162461bcd60e51b8152600401808060200182810382526036815260200180612e506036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526125fd9084906129f4565b600082820183811015610d70576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612a06826001600160a01b031661284b565b612a57576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612a955780518252601f199092019160209182019101612a76565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b509150915081612b53576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612bac57808060200190516020811015612b6f57600080fd5b5051612bac5760405162461bcd60e51b815260040180806020018281038252602a815260200180612e26602a913960400191505060405180910390fd5b50505050565b6000808260000b1315612bdd57612bd683600084900b600a0a63ffffffff612c3016565b9250612c05565b60008260000b1215612c0557612c02836000848103900b600a0a63ffffffff612c8916565b92505b5090919050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b600082612c3f57506000610d73565b82820282848281612c4c57fe5b0414610d705760405162461bcd60e51b8152600401808060200182810382526021815260200180612dd56021913960400191505060405180910390fd5b6000610d7083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183612d525760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d17578181015183820152602001612cff565b50505050905090810190601f168015612d445780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612d5e57fe5b049594505050505056fe6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637443616c6c6572206973206e6f74207468652053747261746567697374206f7220476f7665726e6f7243616c6c6572206973206e6f742074686520476f7665726e6f72000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f7420746865205661756c742c20476f7665726e6f722c206f7220537472617465676973745361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158202d9460819698975a6c9f01af70fc6f240ae6d45252536f47eb9a05cb1514ebb464736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061025e5760003560e01c80635d36b19011610146578063aea173d5116100c3578063c5f0084111610087578063c5f0084114610773578063c7af33521461077b578063d38bfff414610783578063e6cc5432146107a9578063eb03654b146107b1578063fc0cfeee146107ce5761025e565b8063aea173d5146106dd578063b2c9336d14610703578063b888879e14610720578063b890ebf614610728578063bc90106b146107455761025e565b80638e510b521161010a5780638e510b52146106825780638ec489a21461068a57806394828ffd146106a75780639fa1826e146106af578063a403e4d5146106b75761025e565b80635d36b190146104f2578063663e64ce146104fa578063686b37ca14610517578063773540b3146105855780637fe2d393146105ab5761025e565b806329a903ec116101df5780634641257d116101a35780634641257d1461049057806349c1d54d146104985780634cd55c2d146104a057806352d38e5d146104c657806353ca9f24146104ce578063570d8e1d146104ea5761025e565b806329a903ec146103a85780632da845a814610416578063372aa2241461043c5780633b8ae397146104625780633dbc911f146104885761025e565b80631072cbea116102265780631072cbea1461033e578063128a8b051461036a578063175188e8146103725780631edfe3da14610398578063207134b0146103a05761025e565b806309f49bf51461026357806309f6442c1461026d5780630acbda75146102875780630c340a24146102a45780630e5c011e146102c8575b600080fd5b61026b6107f4565b005b610275610873565b60408051918252519081900360200190f35b61026b6004803603602081101561029d57600080fd5b5035610879565b6102ac610952565b604080516001600160a01b039092168252519081900360200190f35b6102ee600480360360208110156102de57600080fd5b50356001600160a01b0316610961565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561032a578181015183820152602001610312565b505050509050019250505060405180910390f35b61026b6004803603604081101561035457600080fd5b506001600160a01b0381351690602001356109d5565b6102ac610ab0565b61026b6004803603602081101561038857600080fd5b50356001600160a01b0316610abf565b610275610d23565b610275610d29565b610275600480360360208110156103be57600080fd5b810190602081018135600160201b8111156103d857600080fd5b8201836020820111156103ea57600080fd5b803590602001918460018302840111600160201b8311171561040b57600080fd5b509092509050610d2f565b61026b6004803603602081101561042c57600080fd5b50356001600160a01b0316610d79565b61026b6004803603602081101561045257600080fd5b50356001600160a01b0316610e14565b61026b6004803603602081101561047857600080fd5b50356001600160a01b0316610eaf565b61026b61101c565b61026b6110b1565b6102ac61114b565b61026b600480360360208110156104b657600080fd5b50356001600160a01b031661115a565b6102756112b7565b6104d66112bd565b604080519115158252519081900360200190f35b6102ac6112cd565b61026b6112dc565b61026b6004803603602081101561051057600080fd5b503561133e565b6102756004803603602081101561052d57600080fd5b810190602081018135600160201b81111561054757600080fd5b82018360208201111561055957600080fd5b803590602001918460018302840111600160201b8311171561057a57600080fd5b5090925090506113c0565b61026b6004803603602081101561059b57600080fd5b50356001600160a01b0316611401565b61026b600480360360808110156105c157600080fd5b6001600160a01b038235811692602081013590911691810190606081016040820135600160201b8111156105f457600080fd5b82018360208201111561060657600080fd5b803590602001918460208302840111600160201b8311171561062757600080fd5b919390929091602081019035600160201b81111561064457600080fd5b82018360208201111561065657600080fd5b803590602001918460208302840111600160201b8311171561067757600080fd5b50909250905061149c565b610275611827565b61026b600480360360208110156106a057600080fd5b503561182d565b61026b6118fc565b61027561197b565b6102ac600480360360208110156106cd57600080fd5b50356001600160a01b0316611981565b61026b600480360360208110156106f357600080fd5b50356001600160a01b031661199c565b61026b6004803603602081101561071957600080fd5b5035611a37565b6102ac611ab9565b61026b6004803603602081101561073e57600080fd5b5035611ac8565b61026b6004803603604081101561075b57600080fd5b506001600160a01b0381358116916020013516611b4a565b61026b611db5565b6104d6611e4a565b61026b6004803603602081101561079957600080fd5b50356001600160a01b0316611e6d565b6104d6611f07565b61026b600480360360208110156107c757600080fd5b5035611f17565b61026b600480360360208110156107e457600080fd5b50356001600160a01b0316611f99565b6107fc611e4a565b61083b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6037805460ff60a01b191690556040517fbc044409505c95b6b851433df96e1beae715c909d8e7c1d6d7ab783300d4e3b990600090a1565b60385481565b610881611e4a565b6108c0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611388811115610917576040805162461bcd60e51b815260206004820152601760248201527f62617369732063616e6e6f742065786365656420353025000000000000000000604482015290519081900360640190fd5b60438190556040805182815290517f56287a45051933ea374811b3d5d165033047be5572cac676f7c28b8be4f746c79181900360200190a150565b600061095c612048565b905090565b60603330148061097b5750603f546001600160a01b031633145b806109895750610989611e4a565b6109c45760405162461bcd60e51b8152600401808060200182810382526030815260200180612df66030913960400191505060405180910390fd5b6109cd8261206d565b90505b919050565b6109dd611e4a565b610a1c576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526033602052604090205460ff1615610a8a576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c7920756e737570706f7274656420617373657473000000000000000000604482015290519081900360640190fd5b610aac610a95610952565b6001600160a01b038416908363ffffffff6125ab16565b5050565b603e546001600160a01b031681565b610ac7611e4a565b610b06576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff16610b6b576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b60365460005b603654811015610bbd57826001600160a01b031660368281548110610b9257fe5b6000918252602090912001546001600160a01b03161415610bb557809150610bbd565b600101610b71565b50603654811015610d0157603680546000198101908110610bda57fe5b600091825260209091200154603680546001600160a01b039092169183908110610c0057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506036805480610c3957fe5b6001900381819060005260206000200160006101000a8154906001600160a01b03021916905590556000829050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ca157600080fd5b505af1158015610cb5573d6000803e3d6000fd5b50505050610cc28361206d565b50604080516001600160a01b038516815290517f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea49181900360200190a1505b506001600160a01b03166000908152603560205260409020805460ff19169055565b60395481565b60435481565b6000610d7083838080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061260292505050565b90505b92915050565b610d81611e4a565b610dc0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1e4af5ac389e8cde1bdaa6830881b6c987c62a45cfb3b33d27d805cde3b577509181900360200190a150565b610e1c611e4a565b610e5b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603780546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb266add5f3044b17d27db796af992cecbe413921b4e8aaaee03c719e16b9806a9181900360200190a150565b610eb7611e4a565b610ef6576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff1615610f64576040805162461bcd60e51b815260206004820152601960248201527f537472617465677920616c726561647920617070726f76656400000000000000604482015290519081900360640190fd5b6040805180820182526001808252600060208084018281526001600160a01b038716808452603583528684209551865460ff19169015151786559051948401949094556036805493840181559091527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890910180546001600160a01b03191683179055825191825291517f960dd94cbb79169f09a4e445d58b895df2d9bffa5b31055d0932d801724a20d1929181900390910190a150565b603f546001600160a01b03163314806110385750611038611e4a565b6110735760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6037805460ff60a81b1916600160a81b1790556040517f71f0e5b62f846a22e0b4d159e516e62fa9c2b8eb570be15f83e67d98a2ee51e090600090a1565b603f546001600160a01b03163314806110cd57506110cd611e4a565b6111085760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b60005b6036548110156111485761113f6036828154811061112557fe5b6000918252602090912001546001600160a01b031661206d565b5060010161110b565b50565b6042546001600160a01b031681565b611162611e4a565b6111a1576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526033602052604090205460ff161561120f576040805162461bcd60e51b815260206004820152601760248201527f417373657420616c726561647920737570706f72746564000000000000000000604482015290519081900360640190fd5b604080516020808201835260018083526001600160a01b0385166000818152603384528581209451855460ff1916901515179094556034805492830181559093527f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c10180546001600160a01b03191683179055825191825291517f4f1ac48525e50059cc1cc6e0e1940ece0dd653a4db4841538d6aef036be2fb7b929181900390910190a150565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b6112e46126ef565b6001600160a01b0316336001600160a01b0316146113335760405162461bcd60e51b8152600401808060200182810382526030815260200180612e866030913960400191505060405180910390fd5b61133c33612714565b565b611346611e4a565b611385576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b60418190556040805182815290517f95201f9c21f26877223b1ff4073936a6484c35495649e60e55730497aeb60d939181900360200190a150565b6000610d7083838080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506127bf92505050565b611409611e4a565b611448576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603f80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee9181900360200190a150565b603f546001600160a01b03163314806114b857506114b8611e4a565b6114f35760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6001600160a01b03861660009081526035602052604090205460ff16611558576040805162461bcd60e51b8152602060048201526015602482015274496e76616c69642066726f6d20537472617465677960581b604482015290519081900360640190fd5b6001600160a01b03851660009081526035602052604090205460ff166115bb576040805162461bcd60e51b8152602060048201526013602482015272496e76616c696420746f20537472617465677960681b604482015290519081900360640190fd5b82811461160f576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b858560005b858110156117c957816001600160a01b031663aa388af688888481811061163757fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561168d57600080fd5b505afa1580156116a1573d6000803e3d6000fd5b505050506040513d60208110156116b757600080fd5b50516116fe576040805162461bcd60e51b8152602060048201526011602482015270105cdcd95d081d5b9cdd5c1c1bdc9d1959607a1b604482015290519081900360640190fd5b826001600160a01b031663d9caed128389898581811061171a57fe5b905060200201356001600160a01b031688888681811061173657fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b1580156117a557600080fd5b505af11580156117b9573d6000803e3d6000fd5b5050600190920191506116149050565b50806001600160a01b031663de5f62686040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561180557600080fd5b505af1158015611819573d6000803e3d6000fd5b505050505050505050505050565b60415481565b611835611e4a565b611874576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b670de0b6b3a76400008111156118c1576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015290519081900360640190fd5b60398190556040805182815290517f41ecb23a0e7865b25f38c268b7c3012220d822929e9edff07326e89d5bb822b59181900360200190a150565b611904611e4a565b611943576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b6037805460ff60a81b191690556040517f891ebab18da80ebeeea06b1b1cede098329c4c008906a98370c2ac7a80b571cb90600090a1565b603a5481565b6040602081905260009182529020546001600160a01b031681565b6119a4611e4a565b6119e3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603e80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b611a3f611e4a565b611a7e576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603a8190556040805182815290517f2ec5fb5a3d2703edc461252d92ccd2799c3c74f01d97212b20388207fa17ae459181900360200190a150565b6037546001600160a01b031681565b611ad0611e4a565b611b0f576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b603b8190556040805182815290517f39367850377ac04920a9a670f2180e7a94d83b15ad302e59875ec58fd10bd37d9181900360200190a150565b603f546001600160a01b0316331480611b665750611b66611e4a565b611ba15760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b604080516001600160a01b0380851682528316602082015281517fba58ce12801c949fa65f41c46ed108671c219baf945fa48d21026cea99ff252a929181900390910190a16001600160a01b03811660009081526035602052604090205460ff16611c4b576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260336020526040902054819060ff16611cb3576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b806001600160a01b031663aa388af6846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611d0957600080fd5b505afa158015611d1d573d6000803e3d6000fd5b505050506040513d6020811015611d3357600080fd5b5051611d86576040805162461bcd60e51b815260206004820152601f60248201527f4173736574206e6f7420737570706f7274656420627920537472617465677900604482015290519081900360640190fd5b506001600160a01b03918216600090815260406020819052902080546001600160a01b03191691909216179055565b603f546001600160a01b0316331480611dd15750611dd1611e4a565b611e0c5760405162461bcd60e51b8152600401808060200182810382526028815260200180612d8d6028913960400191505060405180910390fd5b6037805460ff60a01b1916600160a01b1790556040517f8cff26a5985614b3d30629cc4ab83824bf115aec971b718d8f2f99562032e97290600090a1565b6000611e54612048565b6001600160a01b0316336001600160a01b031614905090565b611e75611e4a565b611eb4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611ebd81612827565b806001600160a01b0316611ecf612048565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b603754600160a81b900460ff1681565b611f1f611e4a565b611f5e576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b60388190556040805182815290517fd6c7508d6658ccee36b7b7d7fd72e5cbaeefb40c64eff24e9ae7470e846304ee9181900360200190a150565b611fa1611e4a565b611fe0576040805162461bcd60e51b815260206004820152601a6024820152600080516020612db5833981519152604482015290519081900360640190fd5b611fe98161284b565b6120245760405162461bcd60e51b8152600401808060200182810382526024815260200180612d696024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606060008290506000816001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156120af57600080fd5b505afa1580156120c3573d6000803e3d6000fd5b505050506040513d60208110156120d957600080fd5b505190506001600160a01b038116156125a457816001600160a01b0316630242241d6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561212757600080fd5b505af115801561213b573d6000803e3d6000fd5b5050603e546001600160a01b03161591506125a49050576000826001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b15801561218d57600080fd5b505afa1580156121a1573d6000803e3d6000fd5b505050506040513d60208110156121b757600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561220557600080fd5b505afa158015612219573d6000803e3d6000fd5b505050506040513d602081101561222f57600080fd5b5051905080156125a157603e5461225a906001600160a01b038481169116600063ffffffff61288716565b603e5461227a906001600160a01b0384811691168363ffffffff61288716565b60408051600380825260808201909252606091602082018380388339019050509050846001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156122d557600080fd5b505afa1580156122e9573d6000803e3d6000fd5b505050506040513d60208110156122ff57600080fd5b50518151829060009061230e57fe5b6001600160a01b03928316602091820292909201810191909152603e54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561236257600080fd5b505afa158015612376573d6000803e3d6000fd5b505050506040513d602081101561238c57600080fd5b505181518290600190811061239d57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060346001815481106123cb57fe5b9060005260206000200160009054906101000a90046001600160a01b0316816002815181106123f657fe5b6001600160a01b039283166020918202929092010152603e54166338ed1739836000843061242c4261070863ffffffff61299a16565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b838110156124a557818101518382015260200161248d565b505050509050019650505050505050600060405180830381600087803b1580156124ce57600080fd5b505af11580156124e2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561250b57600080fd5b8101908080516040519392919084600160201b82111561252a57600080fd5b90830190602082018581111561253f57600080fd5b82518660208202830111600160201b8211171561255b57600080fd5b82525081516020918201928201910280838360005b83811015612588578181015183820152602001612570565b50505050905001604052505050955050505050506109d0565b50505b5050919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526125fd9084906129f4565b505050565b603754604051637bf0c21560e01b81526020600482018181528451602484015284516000946109cd94600a946001600160a01b0390921693637bf0c21593899391928392604490910191908501908083838d5b8381101561266d578181015183820152602001612655565b50505050905090810190601f16801561269a5780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b1580156126b757600080fd5b505afa1580156126cb573d6000803e3d6000fd5b505050506040513d60208110156126e157600080fd5b50519063ffffffff612bb216565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b03811661276f576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316612781612048565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a361114881612c0c565b60375460405163019af6bf60e41b81526020600482018181528451602484015284516000946109cd94600a946001600160a01b03909216936319af6bf093899391928392604490910191908501908083838d831561266d578181015183820152602001612655565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061287f57508115155b949350505050565b80158061290d575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156128df57600080fd5b505afa1580156128f3573d6000803e3d6000fd5b505050506040513d602081101561290957600080fd5b5051155b6129485760405162461bcd60e51b8152600401808060200182810382526036815260200180612e506036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b1790526125fd9084906129f4565b600082820183811015610d70576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612a06826001600160a01b031661284b565b612a57576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612a955780518252601f199092019160209182019101612a76565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612af7576040519150601f19603f3d011682016040523d82523d6000602084013e612afc565b606091505b509150915081612b53576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612bac57808060200190516020811015612b6f57600080fd5b5051612bac5760405162461bcd60e51b815260040180806020018281038252602a815260200180612e26602a913960400191505060405180910390fd5b50505050565b6000808260000b1315612bdd57612bd683600084900b600a0a63ffffffff612c3016565b9250612c05565b60008260000b1215612c0557612c02836000848103900b600a0a63ffffffff612c8916565b92505b5090919050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b600082612c3f57506000610d73565b82820282848281612c4c57fe5b0414610d705760405162461bcd60e51b8152600401808060200182810382526021815260200180612dd56021913960400191505060405180910390fd5b6000610d7083836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060008183612d525760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612d17578181015183820152602001612cff565b50505050905090810190601f168015612d445780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612d5e57fe5b049594505050505056fe6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637443616c6c6572206973206e6f74207468652053747261746567697374206f7220476f7665726e6f7243616c6c6572206973206e6f742074686520476f7665726e6f72000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f7420746865205661756c742c20476f7665726e6f722c206f7220537472617465676973745361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158202d9460819698975a6c9f01af70fc6f240ae6d45252536f47eb9a05cb1514ebb464736f6c634300050b0032", + "solcInputHash": "86605db9d81ca0a1790de251140fb0d9", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":false,\"inputs\":[],\"name\":\"unpauseRebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"redeemFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"setTrusteeFeeBps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyAddr\",\"type\":\"address\"}],\"name\":\"harvest\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"transferToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"priceUSDMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"removeStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultBuffer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setTrusteeAddress\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"setPriceProvider\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"approveStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pauseCapital\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"harvest\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"supportAsset\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebaseThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyAddr\",\"type\":\"address\"}],\"name\":\"withdrawAllFromStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"setMaxSupplyDiff\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setStrategistAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategyFromAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategyToAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"_assets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"}],\"name\":\"reallocate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"priceUSDRedeem\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxSupplyDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"setVaultBuffer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"unpauseCapital\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoAllocateThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetDefaultStrategies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setUniswapAddr\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"setAutoAllocateThreshold\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"priceProvider\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"setRebaseThreshold\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"setAssetDefaultStrategy\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pauseRebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"withdrawAllFromStrategies\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"capitalPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"setRedeemFeeBps\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImpl\",\"type\":\"address\"}],\"name\":\"setAdminImpl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"AssetSupported\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"AssetDefaultStrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebasePaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebaseUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"VaultBufferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"RedeemFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"PriceProviderUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"AllocateThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"RebaseThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyDiffChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_yield\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"YieldDistribution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"TrusteeFeeBpsChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"TrusteeAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"approveStrategy(address)\":{\"details\":\"Add a strategy to the Vault.\",\"params\":{\"_addr\":\"Address of the strategy to add\"}},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"harvest()\":{\"details\":\"Collect reward tokens from all strategies and swap for supported stablecoin via Uniswap\"},\"harvest(address)\":{\"details\":\"Collect reward tokens for a specific strategy and swap for supported stablecoin via Uniswap. Called from the vault.\",\"params\":{\"_strategyAddr\":\"Address of the strategy to collect rewards from\"}},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"pauseCapital()\":{\"details\":\"Set the deposit paused flag to true to prevent capital movement.\"},\"pauseRebase()\":{\"details\":\"Set the deposit paused flag to true to prevent rebasing.\"},\"priceUSDMint(address)\":{\"details\":\"Returns the total price in 18 digit USD for a given asset. Never goes above 1, since that is how we price mints\",\"params\":{\"asset\":\"address of the asset\"},\"return\":\"uint256 USD price of 1 of the asset, in 18 decimal fixed\"},\"priceUSDRedeem(address)\":{\"details\":\"Returns the total price in 18 digit USD for a given asset. Never goes below 1, since that is how we price redeems\",\"params\":{\"asset\":\"Addresss of the asset\"},\"return\":\"uint256 USD price of 1 of the asset, in 18 decimal fixed\"},\"reallocate(address,address,address[],uint256[])\":{\"params\":{\"_amounts\":\"Array of amounts of each corresponding asset to move.\",\"_assets\":\"Array of asset address that will be moved\",\"_strategyFromAddress\":\"Address of Strategy to move assets from.\",\"_strategyToAddress\":\"Address of Strategy to move assets to.\"}},\"removeStrategy(address)\":{\"details\":\"Remove a strategy from the Vault. Removes all invested assets and returns them to the Vault.\",\"params\":{\"_addr\":\"Address of the strategy to remove\"}},\"setAdminImpl(address)\":{\"details\":\"set the implementation for the admin, this needs to be in a base class else we cannot set it\",\"params\":{\"newImpl\":\"address of the implementation\"}},\"setAssetDefaultStrategy(address,address)\":{\"details\":\"Set the default Strategy for an asset, i.e. the one which the asset will be automatically allocated to and withdrawn from\",\"params\":{\"_asset\":\"Address of the asset\",\"_strategy\":\"Address of the Strategy\"}},\"setAutoAllocateThreshold(uint256)\":{\"details\":\"Sets the minimum amount of OUSD in a mint to trigger an automatic allocation of funds afterwords.\",\"params\":{\"_threshold\":\"OUSD amount with 18 fixed decimals.\"}},\"setMaxSupplyDiff(uint256)\":{\"details\":\"Sets the maximum allowable difference between total supply and backing assets' value.\"},\"setPriceProvider(address)\":{\"details\":\"Set address of price provider.\",\"params\":{\"_priceProvider\":\"Address of price provider\"}},\"setRebaseThreshold(uint256)\":{\"details\":\"Set a minimum amount of OUSD in a mint or redeem that triggers a rebase\",\"params\":{\"_threshold\":\"OUSD amount with 18 fixed decimals.\"}},\"setRedeemFeeBps(uint256)\":{\"details\":\"Set a fee in basis points to be charged for a redeem.\",\"params\":{\"_redeemFeeBps\":\"Basis point fee to be charged\"}},\"setStrategistAddr(address)\":{\"details\":\"Set address of Strategist\",\"params\":{\"_address\":\"Address of Strategist\"}},\"setTrusteeAddress(address)\":{\"details\":\"Sets the trusteeAddress that can receive a portion of yield. Setting to the zero address disables this feature.\"},\"setTrusteeFeeBps(uint256)\":{\"details\":\"Sets the TrusteeFeeBps to the percentage of yield that should be received in basis points.\"},\"setUniswapAddr(address)\":{\"details\":\"Set address of Uniswap for performing liquidation of strategy reward tokens\",\"params\":{\"_address\":\"Address of Uniswap\"}},\"setVaultBuffer(uint256)\":{\"details\":\"Set a buffer of assets to keep in the Vault to handle most redemptions without needing to spend gas unwinding assets from a Strategy.\",\"params\":{\"_vaultBuffer\":\"Percentage using 18 decimals. 100% = 1e18.\"}},\"supportAsset(address)\":{\"details\":\"Add a supported asset to the contract, i.e. one that can be to mint OUSD.\",\"params\":{\"_asset\":\"Address of asset\"}},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}},\"transferToken(address,uint256)\":{\"details\":\"Transfer token to governor. Intended for recovering tokens stuck in contract, i.e. mistaken sends.\",\"params\":{\"_amount\":\"Amount of the asset to transfer\",\"_asset\":\"Address for the asset\"}},\"unpauseCapital()\":{\"details\":\"Set the deposit paused flag to false to enable capital movement.\"},\"unpauseRebase()\":{\"details\":\"Set the deposit paused flag to true to allow rebasing.\"},\"withdrawAllFromStrategies()\":{\"details\":\"Withdraws all assets from all the strategies and sends assets to the Vault.\"},\"withdrawAllFromStrategy(address)\":{\"details\":\"Withdraws all assets from the strategy and sends assets to the Vault.\",\"params\":{\"_strategyAddr\":\"Strategy address.\"}}}},\"userdoc\":{\"methods\":{\"reallocate(address,address,address[],uint256[])\":{\"notice\":\"Move assets from one Strategy to another\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/vault/VaultAdmin.sol\":\"VaultAdmin\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"@openzeppelin/upgrades/contracts/Initializable.sol\":{\"content\":\"pragma solidity >=0.4.24 <0.7.0;\\n\\n\\n/**\\n * @title Initializable\\n *\\n * @dev Helper contract to support initializer functions. To use it, replace\\n * the constructor with a function that has the `initializer` modifier.\\n * WARNING: Unlike constructors, initializer functions must be manually\\n * invoked. This applies both to deploying an Initializable contract, as well\\n * as extending an Initializable contract via inheritance.\\n * WARNING: When used with inheritance, manual care must be taken to not invoke\\n * a parent initializer twice, or ensure that all initializers are idempotent,\\n * because this is not dealt with automatically as with constructors.\\n */\\ncontract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to use in the initializer function of a contract.\\n */\\n modifier initializer() {\\n require(initializing || isConstructor() || !initialized, \\\"Contract instance has already been initialized\\\");\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function isConstructor() private view returns (bool) {\\n // extcodesize checks the size of the code stored in an address, and\\n // address returns the current address. Since the code is still not\\n // deployed when running a constructor, any checks on its code size will\\n // yield zero, making it an effective way to detect if a contract is\\n // under construction or not.\\n address self = address(this);\\n uint256 cs;\\n assembly { cs := extcodesize(self) }\\n return cs == 0;\\n }\\n\\n // Reserved storage space to allow for layout changes in the future.\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x9bfec92e36234ecc99b5d37230acb6cd1f99560233753162204104a4897e8721\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x01eab42b6d54fa5389598e0663c24680ecc017e2da848e8ea1c40aeaa8225eef\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IOracle {\\n /**\\n * @dev returns the asset price in USD, 8 decimal digits.\\n */\\n function price(address asset) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x7ddbe1f9ed76feb2fbd52ecfe449e17ef67f7edd5616c6a1eda92a84baa1190f\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to platform\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Deposit the entire balance of all supported assets in the Strategy\\n * to the platform\\n */\\n function depositAll() external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardToken() external;\\n\\n /**\\n * @dev The address of the reward token for the Strategy.\\n */\\n function rewardTokenAddress() external pure returns (address);\\n\\n /**\\n * @dev The threshold (denominated in the reward token) over which the\\n * vault will auto harvest on allocate calls.\\n */\\n function rewardLiquidationThreshold() external pure returns (uint256);\\n}\\n\",\"keccak256\":\"0xe03dc1c97ad3677296da9a7e1e5f708abd227d1147f6f220c5cc8f23c1cd87e0\"},\"contracts/interfaces/uniswap/IUniswapV2Router02.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IUniswapV2Router {\\n function WETH() external pure returns (address);\\n\\n function swapExactTokensForTokens(\\n uint256 amountIn,\\n uint256 amountOutMin,\\n address[] calldata path,\\n address to,\\n uint256 deadline\\n ) external returns (uint256[] memory amounts);\\n\\n function addLiquidity(\\n address tokenA,\\n address tokenB,\\n uint256 amountADesired,\\n uint256 amountBDesired,\\n uint256 amountAMin,\\n uint256 amountBMin,\\n address to,\\n uint256 deadline\\n )\\n external\\n returns (\\n uint256 amountA,\\n uint256 amountB,\\n uint256 liquidity\\n );\\n}\\n\",\"keccak256\":\"0x33943cfab99996faa745df3c21b95b3ed49783b4c3392e4c71e25f6712af509b\"},\"contracts/token/OUSD.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {\\n InitializableERC20Detailed\\n} from \\\"../utils/InitializableERC20Detailed.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\n/**\\n * NOTE that this is an ERC20 token but the invariant that the sum of\\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\\n * rebasing design. Any integrations with OUSD should be aware.\\n */\\n\\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n\\n event TotalSupplyUpdated(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n\\n enum RebaseOptions { NotSet, OptOut, OptIn }\\n\\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\\n uint256 public _totalSupply;\\n mapping(address => mapping(address => uint256)) private _allowances;\\n address public vaultAddress = address(0);\\n mapping(address => uint256) private _creditBalances;\\n uint256 public rebasingCredits;\\n uint256 public rebasingCreditsPerToken;\\n // Frozen address/credits are non rebasing (value is held in contracts which\\n // do not receive yield unless they explicitly opt in)\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) public nonRebasingCreditsPerToken;\\n mapping(address => RebaseOptions) public rebaseState;\\n\\n function initialize(\\n string calldata _nameArg,\\n string calldata _symbolArg,\\n address _vaultAddress\\n ) external onlyGovernor initializer {\\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\\n rebasingCreditsPerToken = 1e18;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Savings Manager contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return The total supply of OUSD.\\n */\\n function totalSupply() public view returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the _amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n if (_creditBalances[_account] == 0) return 0;\\n return\\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n return (_creditBalances[_account], _creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the _amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(\\n _value <= balanceOf(msg.sender),\\n \\\"Transfer greater than balance\\\"\\n );\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The _amount of tokens to be transferred.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(_value <= balanceOf(_from), \\\"Transfer greater than balance\\\");\\n\\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\\n _value\\n );\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Update the count of non rebasing credits in response to a transfer\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value Amount of OUSD to transfer\\n */\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\\n\\n // Credits deducted and credited might be different due to the\\n // differing creditsPerToken used by each account\\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\\n\\n _creditBalances[_from] = _creditBalances[_from].sub(\\n creditsDeducted,\\n \\\"Transfer amount exceeds balance\\\"\\n );\\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\\n\\n if (isNonRebasingTo && !isNonRebasingFrom) {\\n // Transfer to non-rebasing account from rebasing account, credits\\n // are removed from the non rebasing tally\\n nonRebasingSupply = nonRebasingSupply.add(_value);\\n // Update rebasingCredits by subtracting the deducted amount\\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\\n // Transfer to rebasing account from non-rebasing account\\n // Decreasing non-rebasing credits by the amount that was sent\\n nonRebasingSupply = nonRebasingSupply.sub(_value);\\n // Update rebasingCredits by adding the credited amount\\n rebasingCredits = rebasingCredits.add(creditsCredited);\\n }\\n }\\n\\n /**\\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n public\\n view\\n returns (uint256)\\n {\\n return _allowances[_owner][_spender];\\n }\\n\\n /**\\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\\n * msg.sender. This method is included for ERC20 compatibility.\\n * increaseAllowance and decreaseAllowance should be used instead.\\n * Changing an allowance with this method brings the risk that someone may transfer both\\n * the old and the new allowance - if they are both greater than zero - if a transfer\\n * transaction is mined before the later approve() call is mined.\\n *\\n * @param _spender The address which will spend the funds.\\n * @param _value The _amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) public returns (bool) {\\n _allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\\n * This method should be used instead of approve() to avoid the double approval vulnerability\\n * described above.\\n * @param _spender The address which will spend the funds.\\n * @param _addedValue The _amount of tokens to increase the allowance by.\\n */\\n function increaseAllowance(address _spender, uint256 _addedValue)\\n public\\n returns (bool)\\n {\\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\\n .add(_addedValue);\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\\n * @param _spender The address which will spend the funds.\\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\\n */\\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\\n public\\n returns (bool)\\n {\\n uint256 oldValue = _allowances[msg.sender][_spender];\\n if (_subtractedValue >= oldValue) {\\n _allowances[msg.sender][_spender] = 0;\\n } else {\\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\\n }\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Mints new tokens, increasing totalSupply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n _mint(_account, _amount);\\n }\\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 * - `to` cannot be the zero address.\\n */\\n function _mint(address _account, uint256 _amount) internal nonReentrant {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\\n\\n // If the account is non rebasing and doesn't have a set creditsPerToken\\n // then set it i.e. this is a mint from a fresh contract\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.add(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.add(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.add(_amount);\\n\\n require(_totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @dev Burns tokens, decreasing totalSupply.\\n */\\n function burn(address account, uint256 amount) external onlyVault {\\n _burn(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 nonReentrant {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n uint256 currentCredits = _creditBalances[_account];\\n\\n // Remove the credits, burning rounding errors\\n if (\\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\\n ) {\\n // Handle dust from rounding\\n _creditBalances[_account] = 0;\\n } else if (currentCredits > creditAmount) {\\n _creditBalances[_account] = _creditBalances[_account].sub(\\n creditAmount\\n );\\n } else {\\n revert(\\\"Remove exceeds balance\\\");\\n }\\n\\n // Remove from the credit tallies and non-rebasing supply\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.sub(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.sub(_amount);\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n if (nonRebasingCreditsPerToken[_account] != 0) {\\n return nonRebasingCreditsPerToken[_account];\\n } else {\\n return rebasingCreditsPerToken;\\n }\\n }\\n\\n /**\\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\\n * Also, ensure contracts are non-rebasing if they have not opted in.\\n * @param _account Address of the account.\\n */\\n function _isNonRebasingAccount(address _account) internal returns (bool) {\\n bool isContract = Address.isContract(_account);\\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\\n _ensureRebasingMigration(_account);\\n }\\n return nonRebasingCreditsPerToken[_account] > 0;\\n }\\n\\n /**\\n * @dev Ensures internal account for rebasing and non-rebasing credits and\\n * supply is updated following deployment of frozen yield change.\\n */\\n function _ensureRebasingMigration(address _account) internal {\\n if (nonRebasingCreditsPerToken[_account] == 0) {\\n // Set fixed credits per token for this account\\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\\n // Update non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\\n // Update credit tallies\\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\\n }\\n }\\n\\n /**\\n * @dev Add a contract address to the non rebasing exception list. I.e. the\\n * address's balance will be part of rebases so the account will be exposed\\n * to upside and downside.\\n */\\n function rebaseOptIn() public nonReentrant {\\n require(_isNonRebasingAccount(msg.sender), \\\"Account has not opted out\\\");\\n\\n // Convert balance into the same amount at the current exchange rate\\n uint256 newCreditBalance = _creditBalances[msg.sender]\\n .mul(rebasingCreditsPerToken)\\n .div(_creditsPerToken(msg.sender));\\n\\n // Decreasing non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\\n\\n _creditBalances[msg.sender] = newCreditBalance;\\n\\n // Increase rebasing credits, totalSupply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\\n\\n rebaseState[msg.sender] = RebaseOptions.OptIn;\\n\\n // Delete any fixed credits per token\\n delete nonRebasingCreditsPerToken[msg.sender];\\n }\\n\\n /**\\n * @dev Remove a contract address to the non rebasing exception list.\\n */\\n function rebaseOptOut() public nonReentrant {\\n require(!_isNonRebasingAccount(msg.sender), \\\"Account has not opted in\\\");\\n\\n // Increase non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\\n // Set fixed credits per token\\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\\n\\n // Decrease rebasing credits, total supply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\\n\\n // Mark explicitly opted out of rebasing\\n rebaseState[msg.sender] = RebaseOptions.OptOut;\\n }\\n\\n /**\\n * @dev Modify the supply without minting new tokens. This uses a change in\\n * the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n * @return uint256 representing the new total supply.\\n */\\n function changeSupply(uint256 _newTotalSupply)\\n external\\n onlyVault\\n nonReentrant\\n {\\n require(_totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (_totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n return;\\n }\\n\\n _totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\\n _totalSupply.sub(nonRebasingSupply)\\n );\\n\\n require(rebasingCreditsPerToken > 0, \\\"Invalid change in supply\\\");\\n\\n _totalSupply = rebasingCredits\\n .divPrecisely(rebasingCreditsPerToken)\\n .add(nonRebasingSupply);\\n\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n }\\n}\\n\",\"keccak256\":\"0xea89a8b152b363982ba8db340b1e20c3194b2e75a06630cbbf43e3c50fff61a4\"},\"contracts/utils/Helpers.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0xd2ca92e0af883dc1aec5b22caced274e59829e0e30a9e955dcc48b8d921f5cdc\"},\"contracts/utils/InitializableERC20Detailed.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/**\\n * @dev Optional functions from the ERC20 standard.\\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\\n */\\ncontract InitializableERC20Detailed is IERC20 {\\n // Storage gap to skip storage from prior to OUSD reset\\n uint256[100] private _____gap;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\\n * these values are immutable: they can only be set once during\\n * construction.\\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\\n */\\n function _initialize(\\n string memory nameArg,\\n string memory symbolArg,\\n uint8 decimalsArg\\n ) internal {\\n _name = nameArg;\\n _symbol = symbolArg;\\n _decimals = decimalsArg;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view 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 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.\\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 returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x7919369d0f3bd74b4f0ee78a682afe43f91b186cdd0708e303068e4feeb29007\"},\"contracts/utils/StableMath.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n// Based on StableMath from Stability Labs Pty. Ltd.\\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\\n\\nlibrary StableMath {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Scaling unit for use in specific calculations,\\n * where 1 * 10**18, or 1e18 represents a unit '1'\\n */\\n uint256 private constant FULL_SCALE = 1e18;\\n\\n /***************************************\\n Helpers\\n ****************************************/\\n\\n /**\\n * @dev Adjust the scale of an integer\\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\\n */\\n function scaleBy(uint256 x, int8 adjustment)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (adjustment > 0) {\\n x = x.mul(10**uint256(adjustment));\\n } else if (adjustment < 0) {\\n x = x.div(10**uint256(adjustment * -1));\\n }\\n return x;\\n }\\n\\n /***************************************\\n Precise Arithmetic\\n ****************************************/\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\\n return mulTruncateScale(x, y, FULL_SCALE);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @param scale Scale unit\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncateScale(\\n uint256 x,\\n uint256 y,\\n uint256 scale\\n ) internal pure returns (uint256) {\\n // e.g. assume scale = fullScale\\n // z = 10e18 * 9e17 = 9e36\\n uint256 z = x.mul(y);\\n // return 9e38 / 1e18 = 9e18\\n return z.div(scale);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit, rounded up to the closest base unit.\\n */\\n function mulTruncateCeil(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e17 * 17268172638 = 138145381104e17\\n uint256 scaled = x.mul(y);\\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\\n return ceil.div(FULL_SCALE);\\n }\\n\\n /**\\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\\n * @param x Left hand input to division\\n * @param y Right hand input to division\\n * @return Result after multiplying the left operand by the scale, and\\n * executing the division on the right hand input.\\n */\\n function divPrecisely(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e18 * 1e18 = 8e36\\n uint256 z = x.mul(FULL_SCALE);\\n // e.g. 8e36 / 10e18 = 8e17\\n return z.div(y);\\n }\\n}\\n\",\"keccak256\":\"0xa77fccf850feb6d54ba3a6530f92554caef8a67a1ceb573d4f8a5d1bf64ff9d2\"},\"contracts/vault/VaultAdmin.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Vault Admin Contract\\n * @notice The VaultAdmin contract makes configuration and admin calls on the vault.\\n * @author Origin Protocol Inc\\n */\\n\\nimport \\\"./VaultStorage.sol\\\";\\nimport { IOracle } from \\\"../interfaces/IOracle.sol\\\";\\nimport { IUniswapV2Router } from \\\"../interfaces/uniswap/IUniswapV2Router02.sol\\\";\\n\\ncontract VaultAdmin is VaultStorage {\\n /**\\n * @dev Verifies that the caller is the Vault, Governor, or Strategist.\\n */\\n modifier onlyVaultOrGovernorOrStrategist() {\\n require(\\n msg.sender == address(this) ||\\n msg.sender == strategistAddr ||\\n isGovernor(),\\n \\\"Caller is not the Vault, Governor, or Strategist\\\"\\n );\\n _;\\n }\\n\\n modifier onlyGovernorOrStrategist() {\\n require(\\n msg.sender == strategistAddr || isGovernor(),\\n \\\"Caller is not the Strategist or Governor\\\"\\n );\\n _;\\n }\\n\\n /***************************************\\n Configuration\\n ****************************************/\\n\\n /**\\n * @dev Set address of price provider.\\n * @param _priceProvider Address of price provider\\n */\\n function setPriceProvider(address _priceProvider) external onlyGovernor {\\n priceProvider = _priceProvider;\\n emit PriceProviderUpdated(_priceProvider);\\n }\\n\\n /**\\n * @dev Set a fee in basis points to be charged for a redeem.\\n * @param _redeemFeeBps Basis point fee to be charged\\n */\\n function setRedeemFeeBps(uint256 _redeemFeeBps) external onlyGovernor {\\n redeemFeeBps = _redeemFeeBps;\\n emit RedeemFeeUpdated(_redeemFeeBps);\\n }\\n\\n /**\\n * @dev Set a buffer of assets to keep in the Vault to handle most\\n * redemptions without needing to spend gas unwinding assets from a Strategy.\\n * @param _vaultBuffer Percentage using 18 decimals. 100% = 1e18.\\n */\\n function setVaultBuffer(uint256 _vaultBuffer)\\n external\\n onlyGovernorOrStrategist\\n {\\n require(_vaultBuffer <= 1e18, \\\"Invalid value\\\");\\n vaultBuffer = _vaultBuffer;\\n emit VaultBufferUpdated(_vaultBuffer);\\n }\\n\\n /**\\n * @dev Sets the minimum amount of OUSD in a mint to trigger an\\n * automatic allocation of funds afterwords.\\n * @param _threshold OUSD amount with 18 fixed decimals.\\n */\\n function setAutoAllocateThreshold(uint256 _threshold)\\n external\\n onlyGovernor\\n {\\n autoAllocateThreshold = _threshold;\\n emit AllocateThresholdUpdated(_threshold);\\n }\\n\\n /**\\n * @dev Set a minimum amount of OUSD in a mint or redeem that triggers a\\n * rebase\\n * @param _threshold OUSD amount with 18 fixed decimals.\\n */\\n function setRebaseThreshold(uint256 _threshold) external onlyGovernor {\\n rebaseThreshold = _threshold;\\n emit RebaseThresholdUpdated(_threshold);\\n }\\n\\n /**\\n * @dev Set address of Uniswap for performing liquidation of strategy reward\\n * tokens\\n * @param _address Address of Uniswap\\n */\\n function setUniswapAddr(address _address) external onlyGovernor {\\n uniswapAddr = _address;\\n emit UniswapUpdated(_address);\\n }\\n\\n /**\\n * @dev Set address of Strategist\\n * @param _address Address of Strategist\\n */\\n function setStrategistAddr(address _address) external onlyGovernor {\\n strategistAddr = _address;\\n emit StrategistUpdated(_address);\\n }\\n\\n /**\\n * @dev Set the default Strategy for an asset, i.e. the one which the asset\\n will be automatically allocated to and withdrawn from\\n * @param _asset Address of the asset\\n * @param _strategy Address of the Strategy\\n */\\n function setAssetDefaultStrategy(address _asset, address _strategy)\\n external\\n onlyGovernorOrStrategist\\n {\\n emit AssetDefaultStrategyUpdated(_asset, _strategy);\\n require(strategies[_strategy].isSupported, \\\"Strategy not approved\\\");\\n IStrategy strategy = IStrategy(_strategy);\\n require(assets[_asset].isSupported, \\\"Asset is not supported\\\");\\n require(\\n strategy.supportsAsset(_asset),\\n \\\"Asset not supported by Strategy\\\"\\n );\\n assetDefaultStrategies[_asset] = _strategy;\\n }\\n\\n /**\\n * @dev Add a supported asset to the contract, i.e. one that can be\\n * to mint OUSD.\\n * @param _asset Address of asset\\n */\\n function supportAsset(address _asset) external onlyGovernor {\\n require(!assets[_asset].isSupported, \\\"Asset already supported\\\");\\n\\n assets[_asset] = Asset({ isSupported: true });\\n allAssets.push(_asset);\\n\\n // Verify that our oracle supports the asset\\n // slither-disable-next-line unused-return\\n IOracle(priceProvider).price(_asset);\\n\\n emit AssetSupported(_asset);\\n }\\n\\n /**\\n * @dev Add a strategy to the Vault.\\n * @param _addr Address of the strategy to add\\n */\\n function approveStrategy(address _addr) external onlyGovernor {\\n require(!strategies[_addr].isSupported, \\\"Strategy already approved\\\");\\n strategies[_addr] = Strategy({ isSupported: true, _deprecated: 0 });\\n allStrategies.push(_addr);\\n emit StrategyApproved(_addr);\\n }\\n\\n /**\\n * @dev Remove a strategy from the Vault. Removes all invested assets and\\n * returns them to the Vault.\\n * @param _addr Address of the strategy to remove\\n */\\n\\n function removeStrategy(address _addr) external onlyGovernor {\\n require(strategies[_addr].isSupported, \\\"Strategy not approved\\\");\\n\\n // Initialize strategyIndex with out of bounds result so function will\\n // revert if no valid index found\\n uint256 strategyIndex = allStrategies.length;\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n if (allStrategies[i] == _addr) {\\n strategyIndex = i;\\n break;\\n }\\n }\\n\\n if (strategyIndex < allStrategies.length) {\\n allStrategies[strategyIndex] = allStrategies[allStrategies.length -\\n 1];\\n allStrategies.pop();\\n\\n // Withdraw all assets\\n IStrategy strategy = IStrategy(_addr);\\n strategy.withdrawAll();\\n // Call harvest after withdraw in case withdraw triggers\\n // distribution of additional reward tokens (true for Compound)\\n _harvest(_addr);\\n emit StrategyRemoved(_addr);\\n }\\n\\n // Clean up struct in mapping, this can be removed later\\n // See https://github.com/OriginProtocol/origin-dollar/issues/324\\n strategies[_addr].isSupported = false;\\n }\\n\\n /**\\n * @notice Move assets from one Strategy to another\\n * @param _strategyFromAddress Address of Strategy to move assets from.\\n * @param _strategyToAddress Address of Strategy to move assets to.\\n * @param _assets Array of asset address that will be moved\\n * @param _amounts Array of amounts of each corresponding asset to move.\\n */\\n function reallocate(\\n address _strategyFromAddress,\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external onlyGovernorOrStrategist {\\n require(\\n strategies[_strategyFromAddress].isSupported,\\n \\\"Invalid from Strategy\\\"\\n );\\n require(\\n strategies[_strategyToAddress].isSupported,\\n \\\"Invalid to Strategy\\\"\\n );\\n require(_assets.length == _amounts.length, \\\"Parameter length mismatch\\\");\\n\\n IStrategy strategyFrom = IStrategy(_strategyFromAddress);\\n IStrategy strategyTo = IStrategy(_strategyToAddress);\\n\\n for (uint256 i = 0; i < _assets.length; i++) {\\n require(strategyTo.supportsAsset(_assets[i]), \\\"Asset unsupported\\\");\\n // Withdraw from Strategy and pass other Strategy as recipient\\n strategyFrom.withdraw(address(strategyTo), _assets[i], _amounts[i]);\\n }\\n // Tell new Strategy to deposit into protocol\\n strategyTo.depositAll();\\n }\\n\\n /**\\n * @dev Sets the maximum allowable difference between\\n * total supply and backing assets' value.\\n */\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor {\\n maxSupplyDiff = _maxSupplyDiff;\\n emit MaxSupplyDiffChanged(_maxSupplyDiff);\\n }\\n\\n /**\\n * @dev Sets the trusteeAddress that can receive a portion of yield.\\n * Setting to the zero address disables this feature.\\n */\\n function setTrusteeAddress(address _address) external onlyGovernor {\\n trusteeAddress = _address;\\n emit TrusteeAddressChanged(_address);\\n }\\n\\n /**\\n * @dev Sets the TrusteeFeeBps to the percentage of yield that should be\\n * received in basis points.\\n */\\n function setTrusteeFeeBps(uint256 _basis) external onlyGovernor {\\n require(_basis <= 5000, \\\"basis cannot exceed 50%\\\");\\n trusteeFeeBps = _basis;\\n emit TrusteeFeeBpsChanged(_basis);\\n }\\n\\n /***************************************\\n Pause\\n ****************************************/\\n\\n /**\\n * @dev Set the deposit paused flag to true to prevent rebasing.\\n */\\n function pauseRebase() external onlyGovernorOrStrategist {\\n rebasePaused = true;\\n emit RebasePaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to true to allow rebasing.\\n */\\n function unpauseRebase() external onlyGovernor {\\n rebasePaused = false;\\n emit RebaseUnpaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to true to prevent capital movement.\\n */\\n function pauseCapital() external onlyGovernorOrStrategist {\\n capitalPaused = true;\\n emit CapitalPaused();\\n }\\n\\n /**\\n * @dev Set the deposit paused flag to false to enable capital movement.\\n */\\n function unpauseCapital() external onlyGovernorOrStrategist {\\n capitalPaused = false;\\n emit CapitalUnpaused();\\n }\\n\\n /***************************************\\n Rewards\\n ****************************************/\\n\\n /**\\n * @dev Transfer token to governor. Intended for recovering tokens stuck in\\n * contract, i.e. mistaken sends.\\n * @param _asset Address for the asset\\n * @param _amount Amount of the asset to transfer\\n */\\n function transferToken(address _asset, uint256 _amount)\\n external\\n onlyGovernor\\n {\\n require(!assets[_asset].isSupported, \\\"Only unsupported assets\\\");\\n IERC20(_asset).safeTransfer(governor(), _amount);\\n }\\n\\n /**\\n * @dev Collect reward tokens from all strategies and swap for supported\\n * stablecoin via Uniswap\\n */\\n function harvest() external onlyGovernorOrStrategist {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n _harvest(allStrategies[i]);\\n }\\n }\\n\\n /**\\n * @dev Collect reward tokens for a specific strategy and swap for supported\\n * stablecoin via Uniswap. Called from the vault.\\n * @param _strategyAddr Address of the strategy to collect rewards from\\n */\\n function harvest(address _strategyAddr)\\n external\\n onlyVaultOrGovernorOrStrategist\\n returns (uint256[] memory)\\n {\\n return _harvest(_strategyAddr);\\n }\\n\\n /**\\n * @dev Collect reward tokens from a single strategy and swap them for a\\n * supported stablecoin via Uniswap\\n * @param _strategyAddr Address of the strategy to collect rewards from\\n */\\n function _harvest(address _strategyAddr)\\n internal\\n returns (uint256[] memory)\\n {\\n IStrategy strategy = IStrategy(_strategyAddr);\\n address rewardTokenAddress = strategy.rewardTokenAddress();\\n if (rewardTokenAddress != address(0)) {\\n strategy.collectRewardToken();\\n\\n if (uniswapAddr != address(0)) {\\n IERC20 rewardToken = IERC20(strategy.rewardTokenAddress());\\n uint256 rewardTokenAmount = rewardToken.balanceOf(\\n address(this)\\n );\\n if (rewardTokenAmount > 0) {\\n // Give Uniswap full amount allowance\\n rewardToken.safeApprove(uniswapAddr, 0);\\n rewardToken.safeApprove(uniswapAddr, rewardTokenAmount);\\n\\n // Uniswap redemption path\\n address[] memory path = new address[](3);\\n path[0] = strategy.rewardTokenAddress();\\n path[1] = IUniswapV2Router(uniswapAddr).WETH();\\n path[2] = allAssets[1]; // USDT\\n\\n return\\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\\n rewardTokenAmount,\\n uint256(0),\\n path,\\n address(this),\\n now.add(1800)\\n );\\n }\\n }\\n }\\n }\\n\\n /***************************************\\n Pricing\\n ****************************************/\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Never goes above 1, since that is how we price mints\\n * @param asset address of the asset\\n * @return uint256 USD price of 1 of the asset, in 18 decimal fixed\\n */\\n function priceUSDMint(address asset) external view returns (uint256) {\\n uint256 price = IOracle(priceProvider).price(asset);\\n if (price > 1e8) {\\n price = 1e8;\\n }\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return price.scaleBy(10);\\n }\\n\\n /**\\n * @dev Returns the total price in 18 digit USD for a given asset.\\n * Never goes below 1, since that is how we price redeems\\n * @param asset Addresss of the asset\\n * @return uint256 USD price of 1 of the asset, in 18 decimal fixed\\n */\\n function priceUSDRedeem(address asset) external view returns (uint256) {\\n uint256 price = IOracle(priceProvider).price(asset);\\n if (price < 1e8) {\\n price = 1e8;\\n }\\n // Price from Oracle is returned with 8 decimals\\n // scale to 18 so 18-8=10\\n return price.scaleBy(10);\\n }\\n\\n /***************************************\\n Strategies Admin\\n ****************************************/\\n\\n /**\\n * @dev Withdraws all assets from the strategy and sends assets to the Vault.\\n * @param _strategyAddr Strategy address.\\n */\\n function withdrawAllFromStrategy(address _strategyAddr)\\n external\\n onlyGovernorOrStrategist\\n {\\n require(\\n strategies[_strategyAddr].isSupported,\\n \\\"Strategy is not supported\\\"\\n );\\n IStrategy strategy = IStrategy(_strategyAddr);\\n strategy.withdrawAll();\\n }\\n\\n /**\\n * @dev Withdraws all assets from all the strategies and sends assets to the Vault.\\n */\\n function withdrawAllFromStrategies() external onlyGovernorOrStrategist {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n strategy.withdrawAll();\\n }\\n }\\n}\\n\",\"keccak256\":\"0x64bfef426714450ca65e03819bcf4baef47eb20cd882456bbc5cd586b4ee45f0\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD VaultStorage Contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\n\\ncontract VaultStorage is Initializable, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n using SafeMath for int256;\\n using SafeERC20 for IERC20;\\n\\n event AssetSupported(address _asset);\\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\\n event PriceProviderUpdated(address _priceProvider);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event UniswapUpdated(address _address);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n\\n // Assets supported by the Vault, i.e. Stablecoins\\n struct Asset {\\n bool isSupported;\\n }\\n mapping(address => Asset) assets;\\n address[] allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n mapping(address => Strategy) strategies;\\n address[] allStrategies;\\n\\n // Address of the Oracle price provider contract\\n address public priceProvider;\\n // Pausing bools\\n bool public rebasePaused = false;\\n bool public capitalPaused = true;\\n // Redemption fee in basis points\\n uint256 public redeemFeeBps;\\n // Buffer of assets to keep in Vault to handle (most) withdrawals\\n uint256 public vaultBuffer;\\n // Mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n // Mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n OUSD oUSD;\\n\\n //keccak256(\\\"OUSD.vault.governor.admin.impl\\\");\\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\\n\\n // Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n // Address of Uniswap\\n address public uniswapAddr = address(0);\\n\\n // Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n // Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n mapping(address => address) public assetDefaultStrategies;\\n\\n uint256 public maxSupplyDiff;\\n\\n // Trustee contract that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n // Amount of yield collected in basis points\\n uint256 public trusteeFeeBps;\\n\\n /**\\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\\n * @param newImpl address of the implementation\\n */\\n function setAdminImpl(address newImpl) external onlyGovernor {\\n require(\\n Address.isContract(newImpl),\\n \\\"new implementation is not a contract\\\"\\n );\\n bytes32 position = adminImplPosition;\\n assembly {\\n sstore(position, newImpl)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc945fa95b0fb31ae523cf91bd89bbf1289de38b02a8b082b98fed152c00c7746\"}},\"version\":1}", + "bytecode": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b6000805160206200319f83398151915255565b6000805160206200319f8339815191525490565b6130ad80620000f26000396000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80635d36b19011610151578063b2c9336d116100c3578063c7af335211610087578063c7af33521461072b578063c991911214610733578063d38bfff41461073b578063e6cc543214610761578063eb03654b14610769578063fc0cfeee1461078657610274565b8063b2c9336d146106b3578063b888879e146106d0578063b890ebf6146106d8578063bc90106b146106f5578063c5f008411461072357610274565b80638e510b52116101155780638e510b52146106325780638ec489a21461063a57806394828ffd146106575780639fa1826e1461065f578063a403e4d514610667578063aea173d51461068d57610274565b80635d36b190146104e6578063663e64ce146104ee578063773540b31461050b5780637fe2d393146105315780638c5cbb891461060c57610274565b80632da845a8116101ea57806349c1d54d116101ae57806349c1d54d146104665780634cd55c2d1461046e57806352d38e5d1461049457806353ca9f241461049c578063570d8e1d146104b8578063597c8910146104c057610274565b80632da845a8146103e4578063372aa2241461040a5780633b8ae397146104305780633dbc911f146104565780634641257d1461045e57610274565b80631072cbea1161023c5780631072cbea1461035457806310d3fdac14610380578063128a8b05146103a6578063175188e8146103ae5780631edfe3da146103d4578063207134b0146103dc57610274565b806309f49bf51461027957806309f6442c146102835780630acbda751461029d5780630c340a24146102ba5780630e5c011e146102de575b600080fd5b6102816107ac565b005b61028b61082b565b60408051918252519081900360200190f35b610281600480360360208110156102b357600080fd5b5035610831565b6102c261090a565b604080516001600160a01b039092168252519081900360200190f35b610304600480360360208110156102f457600080fd5b50356001600160a01b0316610919565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610340578181015183820152602001610328565b505050509050019250505060405180910390f35b6102816004803603604081101561036a57600080fd5b506001600160a01b03813516906020013561098d565b61028b6004803603602081101561039657600080fd5b50356001600160a01b0316610a68565b6102c2610b10565b610281600480360360208110156103c457600080fd5b50356001600160a01b0316610b1f565b61028b610d83565b61028b610d89565b610281600480360360208110156103fa57600080fd5b50356001600160a01b0316610d8f565b6102816004803603602081101561042057600080fd5b50356001600160a01b0316610e2a565b6102816004803603602081101561044657600080fd5b50356001600160a01b0316610ec5565b610281611032565b6102816110c7565b6102c2611161565b6102816004803603602081101561048457600080fd5b50356001600160a01b0316611170565b61028b611344565b6104a461134a565b604080519115158252519081900360200190f35b6102c261135a565b610281600480360360208110156104d657600080fd5b50356001600160a01b0316611369565b610281611489565b6102816004803603602081101561050457600080fd5b50356114eb565b6102816004803603602081101561052157600080fd5b50356001600160a01b031661156d565b6102816004803603608081101561054757600080fd5b6001600160a01b03823581169260208101359091169181019060608101604082013564010000000081111561057b57600080fd5b82018360208201111561058d57600080fd5b803590602001918460208302840111640100000000831117156105af57600080fd5b9193909290916020810190356401000000008111156105cd57600080fd5b8201836020820111156105df57600080fd5b8035906020019184602083028401116401000000008311171561060157600080fd5b509092509050611608565b61028b6004803603602081101561062257600080fd5b50356001600160a01b0316611993565b61028b611a33565b6102816004803603602081101561065057600080fd5b5035611a39565b610281611b18565b61028b611ba7565b6102c26004803603602081101561067d57600080fd5b50356001600160a01b0316611bad565b610281600480360360208110156106a357600080fd5b50356001600160a01b0316611bc8565b610281600480360360208110156106c957600080fd5b5035611c63565b6102c2611ce5565b610281600480360360208110156106ee57600080fd5b5035611cf4565b6102816004803603604081101561070b57600080fd5b506001600160a01b0381358116916020013516611d76565b610281611fe1565b6104a4612076565b610281612099565b6102816004803603602081101561075157600080fd5b50356001600160a01b031661217c565b6104a4612216565b6102816004803603602081101561077f57600080fd5b5035612226565b6102816004803603602081101561079c57600080fd5b50356001600160a01b03166122a8565b6107b4612076565b6107f3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6037805460ff60a01b191690556040517fbc044409505c95b6b851433df96e1beae715c909d8e7c1d6d7ab783300d4e3b990600090a1565b60385481565b610839612076565b610878576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6113888111156108cf576040805162461bcd60e51b815260206004820152601760248201527f62617369732063616e6e6f742065786365656420353025000000000000000000604482015290519081900360640190fd5b60438190556040805182815290517f56287a45051933ea374811b3d5d165033047be5572cac676f7c28b8be4f746c79181900360200190a150565b6000610914612357565b905090565b6060333014806109335750603f546001600160a01b031633145b806109415750610941612076565b61097c5760405162461bcd60e51b8152600401808060200182810382526030815260200180612fb96030913960400191505060405180910390fd5b6109858261237c565b90505b919050565b610995612076565b6109d4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526033602052604090205460ff1615610a42576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c7920756e737570706f7274656420617373657473000000000000000000604482015290519081900360640190fd5b610a64610a4d61090a565b6001600160a01b038416908363ffffffff6128bc16565b5050565b603754604080516315d5220f60e31b81526001600160a01b03848116600483015291516000938493169163aea91078916024808301926020929190829003018186803b158015610ab757600080fd5b505afa158015610acb573d6000803e3d6000fd5b505050506040513d6020811015610ae157600080fd5b505190506305f5e100811115610af857506305f5e1005b610b0981600a63ffffffff61291316565b9392505050565b603e546001600160a01b031681565b610b27612076565b610b66576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff16610bcb576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b60365460005b603654811015610c1d57826001600160a01b031660368281548110610bf257fe5b6000918252602090912001546001600160a01b03161415610c1557809150610c1d565b600101610bd1565b50603654811015610d6157603680546000198101908110610c3a57fe5b600091825260209091200154603680546001600160a01b039092169183908110610c6057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506036805480610c9957fe5b6001900381819060005260206000200160006101000a8154906001600160a01b03021916905590556000829050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d0157600080fd5b505af1158015610d15573d6000803e3d6000fd5b50505050610d228361237c565b50604080516001600160a01b038516815290517f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea49181900360200190a1505b506001600160a01b03166000908152603560205260409020805460ff19169055565b60395481565b60435481565b610d97612076565b610dd6576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1e4af5ac389e8cde1bdaa6830881b6c987c62a45cfb3b33d27d805cde3b577509181900360200190a150565b610e32612076565b610e71576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603780546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb266add5f3044b17d27db796af992cecbe413921b4e8aaaee03c719e16b9806a9181900360200190a150565b610ecd612076565b610f0c576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff1615610f7a576040805162461bcd60e51b815260206004820152601960248201527f537472617465677920616c726561647920617070726f76656400000000000000604482015290519081900360640190fd5b6040805180820182526001808252600060208084018281526001600160a01b038716808452603583528684209551865460ff19169015151786559051948401949094556036805493840181559091527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890910180546001600160a01b03191683179055825191825291517f960dd94cbb79169f09a4e445d58b895df2d9bffa5b31055d0932d801724a20d1929181900390910190a150565b603f546001600160a01b031633148061104e575061104e612076565b6110895760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a81b1916600160a81b1790556040517f71f0e5b62f846a22e0b4d159e516e62fa9c2b8eb570be15f83e67d98a2ee51e090600090a1565b603f546001600160a01b03163314806110e357506110e3612076565b61111e5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b60005b60365481101561115e576111556036828154811061113b57fe5b6000918252602090912001546001600160a01b031661237c565b50600101611121565b50565b6042546001600160a01b031681565b611178612076565b6111b7576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526033602052604090205460ff1615611225576040805162461bcd60e51b815260206004820152601760248201527f417373657420616c726561647920737570706f72746564000000000000000000604482015290519081900360640190fd5b604080516020808201835260018083526001600160a01b038581166000818152603385528681209551865460ff1916901515179095556034805493840181559094527f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c190910180546001600160a01b0319168417905560375484516315d5220f60e31b81526004810194909452935193169263aea91078926024808201939291829003018186803b1580156112d957600080fd5b505afa1580156112ed573d6000803e3d6000fd5b505050506040513d602081101561130357600080fd5b5050604080516001600160a01b038316815290517f4f1ac48525e50059cc1cc6e0e1940ece0dd653a4db4841538d6aef036be2fb7b9181900360200190a150565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b603f546001600160a01b03163314806113855750611385612076565b6113c05760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6001600160a01b03811660009081526035602052604090205460ff1661142d576040805162461bcd60e51b815260206004820152601960248201527f5374726174656779206973206e6f7420737570706f7274656400000000000000604482015290519081900360640190fd5b6000819050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561146d57600080fd5b505af1158015611481573d6000803e3d6000fd5b505050505050565b61149161296f565b6001600160a01b0316336001600160a01b0316146114e05760405162461bcd60e51b81526004018080602001828103825260308152602001806130496030913960400191505060405180910390fd5b6114e933612994565b565b6114f3612076565b611532576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b60418190556040805182815290517f95201f9c21f26877223b1ff4073936a6484c35495649e60e55730497aeb60d939181900360200190a150565b611575612076565b6115b4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603f80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee9181900360200190a150565b603f546001600160a01b03163314806116245750611624612076565b61165f5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6001600160a01b03861660009081526035602052604090205460ff166116c4576040805162461bcd60e51b8152602060048201526015602482015274496e76616c69642066726f6d20537472617465677960581b604482015290519081900360640190fd5b6001600160a01b03851660009081526035602052604090205460ff16611727576040805162461bcd60e51b8152602060048201526013602482015272496e76616c696420746f20537472617465677960681b604482015290519081900360640190fd5b82811461177b576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b858560005b8581101561193557816001600160a01b031663aa388af68888848181106117a357fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156117f957600080fd5b505afa15801561180d573d6000803e3d6000fd5b505050506040513d602081101561182357600080fd5b505161186a576040805162461bcd60e51b8152602060048201526011602482015270105cdcd95d081d5b9cdd5c1c1bdc9d1959607a1b604482015290519081900360640190fd5b826001600160a01b031663d9caed128389898581811061188657fe5b905060200201356001600160a01b03168888868181106118a257fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561191157600080fd5b505af1158015611925573d6000803e3d6000fd5b5050600190920191506117809050565b50806001600160a01b031663de5f62686040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561197157600080fd5b505af1158015611985573d6000803e3d6000fd5b505050505050505050505050565b603754604080516315d5220f60e31b81526001600160a01b03848116600483015291516000938493169163aea91078916024808301926020929190829003018186803b1580156119e257600080fd5b505afa1580156119f6573d6000803e3d6000fd5b505050506040513d6020811015611a0c57600080fd5b505190506305f5e100811015610af857506305f5e100610b0981600a63ffffffff61291316565b60415481565b603f546001600160a01b0316331480611a555750611a55612076565b611a905760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b670de0b6b3a7640000811115611add576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015290519081900360640190fd5b60398190556040805182815290517f41ecb23a0e7865b25f38c268b7c3012220d822929e9edff07326e89d5bb822b59181900360200190a150565b603f546001600160a01b0316331480611b345750611b34612076565b611b6f5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a81b191690556040517f891ebab18da80ebeeea06b1b1cede098329c4c008906a98370c2ac7a80b571cb90600090a1565b603a5481565b6040602081905260009182529020546001600160a01b031681565b611bd0612076565b611c0f576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603e80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b611c6b612076565b611caa576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603a8190556040805182815290517f2ec5fb5a3d2703edc461252d92ccd2799c3c74f01d97212b20388207fa17ae459181900360200190a150565b6037546001600160a01b031681565b611cfc612076565b611d3b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603b8190556040805182815290517f39367850377ac04920a9a670f2180e7a94d83b15ad302e59875ec58fd10bd37d9181900360200190a150565b603f546001600160a01b0316331480611d925750611d92612076565b611dcd5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b604080516001600160a01b0380851682528316602082015281517fba58ce12801c949fa65f41c46ed108671c219baf945fa48d21026cea99ff252a929181900390910190a16001600160a01b03811660009081526035602052604090205460ff16611e77576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260336020526040902054819060ff16611edf576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b806001600160a01b031663aa388af6846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611f3557600080fd5b505afa158015611f49573d6000803e3d6000fd5b505050506040513d6020811015611f5f57600080fd5b5051611fb2576040805162461bcd60e51b815260206004820152601f60248201527f4173736574206e6f7420737570706f7274656420627920537472617465677900604482015290519081900360640190fd5b506001600160a01b03918216600090815260406020819052902080546001600160a01b03191691909216179055565b603f546001600160a01b0316331480611ffd5750611ffd612076565b6120385760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a01b1916600160a01b1790556040517f8cff26a5985614b3d30629cc4ab83824bf115aec971b718d8f2f99562032e97290600090a1565b6000612080612357565b6001600160a01b0316336001600160a01b031614905090565b603f546001600160a01b03163314806120b557506120b5612076565b6120f05760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b60005b60365481101561115e5760006036828154811061210c57fe5b60009182526020822001546040805163429c145b60e11b815290516001600160a01b039092169350839263853828b69260048084019382900301818387803b15801561215757600080fd5b505af115801561216b573d6000803e3d6000fd5b5050600190930192506120f3915050565b612184612076565b6121c3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6121cc81612a3f565b806001600160a01b03166121de612357565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b603754600160a81b900460ff1681565b61222e612076565b61226d576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b60388190556040805182815290517fd6c7508d6658ccee36b7b7d7fd72e5cbaeefb40c64eff24e9ae7470e846304ee9181900360200190a150565b6122b0612076565b6122ef576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6122f881612a63565b6123335760405162461bcd60e51b8152600401808060200182810382526024815260200180612f2c6024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606060008290506000816001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156123be57600080fd5b505afa1580156123d2573d6000803e3d6000fd5b505050506040513d60208110156123e857600080fd5b505190506001600160a01b038116156128b557816001600160a01b0316630242241d6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561243657600080fd5b505af115801561244a573d6000803e3d6000fd5b5050603e546001600160a01b03161591506128b59050576000826001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b15801561249c57600080fd5b505afa1580156124b0573d6000803e3d6000fd5b505050506040513d60208110156124c657600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561251457600080fd5b505afa158015612528573d6000803e3d6000fd5b505050506040513d602081101561253e57600080fd5b5051905080156128b257603e54612569906001600160a01b038481169116600063ffffffff612a9f16565b603e54612589906001600160a01b0384811691168363ffffffff612a9f16565b60408051600380825260808201909252606091602082018380388339019050509050846001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e457600080fd5b505afa1580156125f8573d6000803e3d6000fd5b505050506040513d602081101561260e57600080fd5b50518151829060009061261d57fe5b6001600160a01b03928316602091820292909201810191909152603e54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561267157600080fd5b505afa158015612685573d6000803e3d6000fd5b505050506040513d602081101561269b57600080fd5b50518151829060019081106126ac57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060346001815481106126da57fe5b9060005260206000200160009054906101000a90046001600160a01b03168160028151811061270557fe5b6001600160a01b039283166020918202929092010152603e54166338ed1739836000843061273b4261070863ffffffff612bb216565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b838110156127b457818101518382015260200161279c565b505050509050019650505050505050600060405180830381600087803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561281a57600080fd5b810190808051604051939291908464010000000082111561283a57600080fd5b90830190602082018581111561284f57600080fd5b825186602082028301116401000000008211171561286c57600080fd5b82525081516020918201928201910280838360005b83811015612899578181015183820152602001612881565b5050505090500160405250505095505050505050610988565b50505b5050919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261290e908490612c0c565b505050565b6000808260000b131561293e5761293783600084900b600a0a63ffffffff612dca16565b9250612966565b60008260000b121561296657612963836000848103900b600a0a63ffffffff612e2316565b92505b50815b92915050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b0381166129ef576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316612a01612357565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a361115e81612e65565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612a9757508115155b949350505050565b801580612b25575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015612af757600080fd5b505afa158015612b0b573d6000803e3d6000fd5b505050506040513d6020811015612b2157600080fd5b5051155b612b605760405162461bcd60e51b81526004018080602001828103825260368152602001806130136036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261290e908490612c0c565b600082820183811015610b09576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612c1e826001600160a01b0316612a63565b612c6f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612cad5780518252601f199092019160209182019101612c8e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612d0f576040519150601f19603f3d011682016040523d82523d6000602084013e612d14565b606091505b509150915081612d6b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612dc457808060200190516020811015612d8757600080fd5b5051612dc45760405162461bcd60e51b815260040180806020018281038252602a815260200180612fe9602a913960400191505060405180910390fd5b50505050565b600082612dd957506000612969565b82820282848281612de657fe5b0414610b095760405162461bcd60e51b8152600401808060200182810382526021815260200180612f986021913960400191505060405180910390fd5b6000610b0983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612e89565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008183612f155760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612eda578181015183820152602001612ec2565b50505050905090810190601f168015612f075780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612f2157fe5b049594505050505056fe6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637443616c6c6572206973206e6f74207468652053747261746567697374206f7220476f7665726e6f7243616c6c6572206973206e6f742074686520476f7665726e6f72000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f7420746865205661756c742c20476f7665726e6f722c206f7220537472617465676973745361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820e94b2b8fd98de32dfe8ffdf996c6bf9691663e7573f493e264a8b4d0c4a0f08864736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102745760003560e01c80635d36b19011610151578063b2c9336d116100c3578063c7af335211610087578063c7af33521461072b578063c991911214610733578063d38bfff41461073b578063e6cc543214610761578063eb03654b14610769578063fc0cfeee1461078657610274565b8063b2c9336d146106b3578063b888879e146106d0578063b890ebf6146106d8578063bc90106b146106f5578063c5f008411461072357610274565b80638e510b52116101155780638e510b52146106325780638ec489a21461063a57806394828ffd146106575780639fa1826e1461065f578063a403e4d514610667578063aea173d51461068d57610274565b80635d36b190146104e6578063663e64ce146104ee578063773540b31461050b5780637fe2d393146105315780638c5cbb891461060c57610274565b80632da845a8116101ea57806349c1d54d116101ae57806349c1d54d146104665780634cd55c2d1461046e57806352d38e5d1461049457806353ca9f241461049c578063570d8e1d146104b8578063597c8910146104c057610274565b80632da845a8146103e4578063372aa2241461040a5780633b8ae397146104305780633dbc911f146104565780634641257d1461045e57610274565b80631072cbea1161023c5780631072cbea1461035457806310d3fdac14610380578063128a8b05146103a6578063175188e8146103ae5780631edfe3da146103d4578063207134b0146103dc57610274565b806309f49bf51461027957806309f6442c146102835780630acbda751461029d5780630c340a24146102ba5780630e5c011e146102de575b600080fd5b6102816107ac565b005b61028b61082b565b60408051918252519081900360200190f35b610281600480360360208110156102b357600080fd5b5035610831565b6102c261090a565b604080516001600160a01b039092168252519081900360200190f35b610304600480360360208110156102f457600080fd5b50356001600160a01b0316610919565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610340578181015183820152602001610328565b505050509050019250505060405180910390f35b6102816004803603604081101561036a57600080fd5b506001600160a01b03813516906020013561098d565b61028b6004803603602081101561039657600080fd5b50356001600160a01b0316610a68565b6102c2610b10565b610281600480360360208110156103c457600080fd5b50356001600160a01b0316610b1f565b61028b610d83565b61028b610d89565b610281600480360360208110156103fa57600080fd5b50356001600160a01b0316610d8f565b6102816004803603602081101561042057600080fd5b50356001600160a01b0316610e2a565b6102816004803603602081101561044657600080fd5b50356001600160a01b0316610ec5565b610281611032565b6102816110c7565b6102c2611161565b6102816004803603602081101561048457600080fd5b50356001600160a01b0316611170565b61028b611344565b6104a461134a565b604080519115158252519081900360200190f35b6102c261135a565b610281600480360360208110156104d657600080fd5b50356001600160a01b0316611369565b610281611489565b6102816004803603602081101561050457600080fd5b50356114eb565b6102816004803603602081101561052157600080fd5b50356001600160a01b031661156d565b6102816004803603608081101561054757600080fd5b6001600160a01b03823581169260208101359091169181019060608101604082013564010000000081111561057b57600080fd5b82018360208201111561058d57600080fd5b803590602001918460208302840111640100000000831117156105af57600080fd5b9193909290916020810190356401000000008111156105cd57600080fd5b8201836020820111156105df57600080fd5b8035906020019184602083028401116401000000008311171561060157600080fd5b509092509050611608565b61028b6004803603602081101561062257600080fd5b50356001600160a01b0316611993565b61028b611a33565b6102816004803603602081101561065057600080fd5b5035611a39565b610281611b18565b61028b611ba7565b6102c26004803603602081101561067d57600080fd5b50356001600160a01b0316611bad565b610281600480360360208110156106a357600080fd5b50356001600160a01b0316611bc8565b610281600480360360208110156106c957600080fd5b5035611c63565b6102c2611ce5565b610281600480360360208110156106ee57600080fd5b5035611cf4565b6102816004803603604081101561070b57600080fd5b506001600160a01b0381358116916020013516611d76565b610281611fe1565b6104a4612076565b610281612099565b6102816004803603602081101561075157600080fd5b50356001600160a01b031661217c565b6104a4612216565b6102816004803603602081101561077f57600080fd5b5035612226565b6102816004803603602081101561079c57600080fd5b50356001600160a01b03166122a8565b6107b4612076565b6107f3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6037805460ff60a01b191690556040517fbc044409505c95b6b851433df96e1beae715c909d8e7c1d6d7ab783300d4e3b990600090a1565b60385481565b610839612076565b610878576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6113888111156108cf576040805162461bcd60e51b815260206004820152601760248201527f62617369732063616e6e6f742065786365656420353025000000000000000000604482015290519081900360640190fd5b60438190556040805182815290517f56287a45051933ea374811b3d5d165033047be5572cac676f7c28b8be4f746c79181900360200190a150565b6000610914612357565b905090565b6060333014806109335750603f546001600160a01b031633145b806109415750610941612076565b61097c5760405162461bcd60e51b8152600401808060200182810382526030815260200180612fb96030913960400191505060405180910390fd5b6109858261237c565b90505b919050565b610995612076565b6109d4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526033602052604090205460ff1615610a42576040805162461bcd60e51b815260206004820152601760248201527f4f6e6c7920756e737570706f7274656420617373657473000000000000000000604482015290519081900360640190fd5b610a64610a4d61090a565b6001600160a01b038416908363ffffffff6128bc16565b5050565b603754604080516315d5220f60e31b81526001600160a01b03848116600483015291516000938493169163aea91078916024808301926020929190829003018186803b158015610ab757600080fd5b505afa158015610acb573d6000803e3d6000fd5b505050506040513d6020811015610ae157600080fd5b505190506305f5e100811115610af857506305f5e1005b610b0981600a63ffffffff61291316565b9392505050565b603e546001600160a01b031681565b610b27612076565b610b66576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff16610bcb576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b60365460005b603654811015610c1d57826001600160a01b031660368281548110610bf257fe5b6000918252602090912001546001600160a01b03161415610c1557809150610c1d565b600101610bd1565b50603654811015610d6157603680546000198101908110610c3a57fe5b600091825260209091200154603680546001600160a01b039092169183908110610c6057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506036805480610c9957fe5b6001900381819060005260206000200160006101000a8154906001600160a01b03021916905590556000829050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610d0157600080fd5b505af1158015610d15573d6000803e3d6000fd5b50505050610d228361237c565b50604080516001600160a01b038516815290517f09a1db4b80c32706328728508c941a6b954f31eb5affd32f236c1fd405f8fea49181900360200190a1505b506001600160a01b03166000908152603560205260409020805460ff19169055565b60395481565b60435481565b610d97612076565b610dd6576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f1e4af5ac389e8cde1bdaa6830881b6c987c62a45cfb3b33d27d805cde3b577509181900360200190a150565b610e32612076565b610e71576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603780546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb266add5f3044b17d27db796af992cecbe413921b4e8aaaee03c719e16b9806a9181900360200190a150565b610ecd612076565b610f0c576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526035602052604090205460ff1615610f7a576040805162461bcd60e51b815260206004820152601960248201527f537472617465677920616c726561647920617070726f76656400000000000000604482015290519081900360640190fd5b6040805180820182526001808252600060208084018281526001600160a01b038716808452603583528684209551865460ff19169015151786559051948401949094556036805493840181559091527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890910180546001600160a01b03191683179055825191825291517f960dd94cbb79169f09a4e445d58b895df2d9bffa5b31055d0932d801724a20d1929181900390910190a150565b603f546001600160a01b031633148061104e575061104e612076565b6110895760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a81b1916600160a81b1790556040517f71f0e5b62f846a22e0b4d159e516e62fa9c2b8eb570be15f83e67d98a2ee51e090600090a1565b603f546001600160a01b03163314806110e357506110e3612076565b61111e5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b60005b60365481101561115e576111556036828154811061113b57fe5b6000918252602090912001546001600160a01b031661237c565b50600101611121565b50565b6042546001600160a01b031681565b611178612076565b6111b7576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526033602052604090205460ff1615611225576040805162461bcd60e51b815260206004820152601760248201527f417373657420616c726561647920737570706f72746564000000000000000000604482015290519081900360640190fd5b604080516020808201835260018083526001600160a01b038581166000818152603385528681209551865460ff1916901515179095556034805493840181559094527f46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c190910180546001600160a01b0319168417905560375484516315d5220f60e31b81526004810194909452935193169263aea91078926024808201939291829003018186803b1580156112d957600080fd5b505afa1580156112ed573d6000803e3d6000fd5b505050506040513d602081101561130357600080fd5b5050604080516001600160a01b038316815290517f4f1ac48525e50059cc1cc6e0e1940ece0dd653a4db4841538d6aef036be2fb7b9181900360200190a150565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b603f546001600160a01b03163314806113855750611385612076565b6113c05760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6001600160a01b03811660009081526035602052604090205460ff1661142d576040805162461bcd60e51b815260206004820152601960248201527f5374726174656779206973206e6f7420737570706f7274656400000000000000604482015290519081900360640190fd5b6000819050806001600160a01b031663853828b66040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561146d57600080fd5b505af1158015611481573d6000803e3d6000fd5b505050505050565b61149161296f565b6001600160a01b0316336001600160a01b0316146114e05760405162461bcd60e51b81526004018080602001828103825260308152602001806130496030913960400191505060405180910390fd5b6114e933612994565b565b6114f3612076565b611532576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b60418190556040805182815290517f95201f9c21f26877223b1ff4073936a6484c35495649e60e55730497aeb60d939181900360200190a150565b611575612076565b6115b4576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603f80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee9181900360200190a150565b603f546001600160a01b03163314806116245750611624612076565b61165f5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6001600160a01b03861660009081526035602052604090205460ff166116c4576040805162461bcd60e51b8152602060048201526015602482015274496e76616c69642066726f6d20537472617465677960581b604482015290519081900360640190fd5b6001600160a01b03851660009081526035602052604090205460ff16611727576040805162461bcd60e51b8152602060048201526013602482015272496e76616c696420746f20537472617465677960681b604482015290519081900360640190fd5b82811461177b576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b858560005b8581101561193557816001600160a01b031663aa388af68888848181106117a357fe5b905060200201356001600160a01b03166040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156117f957600080fd5b505afa15801561180d573d6000803e3d6000fd5b505050506040513d602081101561182357600080fd5b505161186a576040805162461bcd60e51b8152602060048201526011602482015270105cdcd95d081d5b9cdd5c1c1bdc9d1959607a1b604482015290519081900360640190fd5b826001600160a01b031663d9caed128389898581811061188657fe5b905060200201356001600160a01b03168888868181106118a257fe5b905060200201356040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b15801561191157600080fd5b505af1158015611925573d6000803e3d6000fd5b5050600190920191506117809050565b50806001600160a01b031663de5f62686040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561197157600080fd5b505af1158015611985573d6000803e3d6000fd5b505050505050505050505050565b603754604080516315d5220f60e31b81526001600160a01b03848116600483015291516000938493169163aea91078916024808301926020929190829003018186803b1580156119e257600080fd5b505afa1580156119f6573d6000803e3d6000fd5b505050506040513d6020811015611a0c57600080fd5b505190506305f5e100811015610af857506305f5e100610b0981600a63ffffffff61291316565b60415481565b603f546001600160a01b0316331480611a555750611a55612076565b611a905760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b670de0b6b3a7640000811115611add576040805162461bcd60e51b815260206004820152600d60248201526c496e76616c69642076616c756560981b604482015290519081900360640190fd5b60398190556040805182815290517f41ecb23a0e7865b25f38c268b7c3012220d822929e9edff07326e89d5bb822b59181900360200190a150565b603f546001600160a01b0316331480611b345750611b34612076565b611b6f5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a81b191690556040517f891ebab18da80ebeeea06b1b1cede098329c4c008906a98370c2ac7a80b571cb90600090a1565b603a5481565b6040602081905260009182529020546001600160a01b031681565b611bd0612076565b611c0f576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603e80546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fca20db57f4368388dd6766259da48cd22a485cba21ee6ec8c519007cb66dfd039181900360200190a150565b611c6b612076565b611caa576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603a8190556040805182815290517f2ec5fb5a3d2703edc461252d92ccd2799c3c74f01d97212b20388207fa17ae459181900360200190a150565b6037546001600160a01b031681565b611cfc612076565b611d3b576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b603b8190556040805182815290517f39367850377ac04920a9a670f2180e7a94d83b15ad302e59875ec58fd10bd37d9181900360200190a150565b603f546001600160a01b0316331480611d925750611d92612076565b611dcd5760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b604080516001600160a01b0380851682528316602082015281517fba58ce12801c949fa65f41c46ed108671c219baf945fa48d21026cea99ff252a929181900390910190a16001600160a01b03811660009081526035602052604090205460ff16611e77576040805162461bcd60e51b815260206004820152601560248201527414dd1c985d1959de481b9bdd08185c1c1c9bdd9959605a1b604482015290519081900360640190fd5b6001600160a01b038216600090815260336020526040902054819060ff16611edf576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b806001600160a01b031663aa388af6846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611f3557600080fd5b505afa158015611f49573d6000803e3d6000fd5b505050506040513d6020811015611f5f57600080fd5b5051611fb2576040805162461bcd60e51b815260206004820152601f60248201527f4173736574206e6f7420737570706f7274656420627920537472617465677900604482015290519081900360640190fd5b506001600160a01b03918216600090815260406020819052902080546001600160a01b03191691909216179055565b603f546001600160a01b0316331480611ffd5750611ffd612076565b6120385760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b6037805460ff60a01b1916600160a01b1790556040517f8cff26a5985614b3d30629cc4ab83824bf115aec971b718d8f2f99562032e97290600090a1565b6000612080612357565b6001600160a01b0316336001600160a01b031614905090565b603f546001600160a01b03163314806120b557506120b5612076565b6120f05760405162461bcd60e51b8152600401808060200182810382526028815260200180612f506028913960400191505060405180910390fd5b60005b60365481101561115e5760006036828154811061210c57fe5b60009182526020822001546040805163429c145b60e11b815290516001600160a01b039092169350839263853828b69260048084019382900301818387803b15801561215757600080fd5b505af115801561216b573d6000803e3d6000fd5b5050600190930192506120f3915050565b612184612076565b6121c3576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6121cc81612a3f565b806001600160a01b03166121de612357565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b603754600160a81b900460ff1681565b61222e612076565b61226d576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b60388190556040805182815290517fd6c7508d6658ccee36b7b7d7fd72e5cbaeefb40c64eff24e9ae7470e846304ee9181900360200190a150565b6122b0612076565b6122ef576040805162461bcd60e51b815260206004820152601a6024820152600080516020612f78833981519152604482015290519081900360640190fd5b6122f881612a63565b6123335760405162461bcd60e51b8152600401808060200182810382526024815260200180612f2c6024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606060008290506000816001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156123be57600080fd5b505afa1580156123d2573d6000803e3d6000fd5b505050506040513d60208110156123e857600080fd5b505190506001600160a01b038116156128b557816001600160a01b0316630242241d6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561243657600080fd5b505af115801561244a573d6000803e3d6000fd5b5050603e546001600160a01b03161591506128b59050576000826001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b15801561249c57600080fd5b505afa1580156124b0573d6000803e3d6000fd5b505050506040513d60208110156124c657600080fd5b5051604080516370a0823160e01b815230600482015290519192506000916001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561251457600080fd5b505afa158015612528573d6000803e3d6000fd5b505050506040513d602081101561253e57600080fd5b5051905080156128b257603e54612569906001600160a01b038481169116600063ffffffff612a9f16565b603e54612589906001600160a01b0384811691168363ffffffff612a9f16565b60408051600380825260808201909252606091602082018380388339019050509050846001600160a01b031663125f9e336040518163ffffffff1660e01b815260040160206040518083038186803b1580156125e457600080fd5b505afa1580156125f8573d6000803e3d6000fd5b505050506040513d602081101561260e57600080fd5b50518151829060009061261d57fe5b6001600160a01b03928316602091820292909201810191909152603e54604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b15801561267157600080fd5b505afa158015612685573d6000803e3d6000fd5b505050506040513d602081101561269b57600080fd5b50518151829060019081106126ac57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060346001815481106126da57fe5b9060005260206000200160009054906101000a90046001600160a01b03168160028151811061270557fe5b6001600160a01b039283166020918202929092010152603e54166338ed1739836000843061273b4261070863ffffffff612bb216565b6040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b838110156127b457818101518382015260200161279c565b505050509050019650505050505050600060405180830381600087803b1580156127dd57600080fd5b505af11580156127f1573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561281a57600080fd5b810190808051604051939291908464010000000082111561283a57600080fd5b90830190602082018581111561284f57600080fd5b825186602082028301116401000000008211171561286c57600080fd5b82525081516020918201928201910280838360005b83811015612899578181015183820152602001612881565b5050505090500160405250505095505050505050610988565b50505b5050919050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261290e908490612c0c565b505050565b6000808260000b131561293e5761293783600084900b600a0a63ffffffff612dca16565b9250612966565b60008260000b121561296657612963836000848103900b600a0a63ffffffff612e2316565b92505b50815b92915050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b0381166129ef576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316612a01612357565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a361115e81612e65565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612a9757508115155b949350505050565b801580612b25575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b158015612af757600080fd5b505afa158015612b0b573d6000803e3d6000fd5b505050506040513d6020811015612b2157600080fd5b5051155b612b605760405162461bcd60e51b81526004018080602001828103825260368152602001806130136036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261290e908490612c0c565b600082820183811015610b09576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b612c1e826001600160a01b0316612a63565b612c6f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612cad5780518252601f199092019160209182019101612c8e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612d0f576040519150601f19603f3d011682016040523d82523d6000602084013e612d14565b606091505b509150915081612d6b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115612dc457808060200190516020811015612d8757600080fd5b5051612dc45760405162461bcd60e51b815260040180806020018281038252602a815260200180612fe9602a913960400191505060405180910390fd5b50505050565b600082612dd957506000612969565b82820282848281612de657fe5b0414610b095760405162461bcd60e51b8152600401808060200182810382526021815260200180612f986021913960400191505060405180910390fd5b6000610b0983836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612e89565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008183612f155760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612eda578181015183820152602001612ec2565b50505050905090810190601f168015612f075780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506000838581612f2157fe5b049594505050505056fe6e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e747261637443616c6c6572206973206e6f74207468652053747261746567697374206f7220476f7665726e6f7243616c6c6572206973206e6f742074686520476f7665726e6f72000000000000536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f7420746865205661756c742c20476f7665726e6f722c206f7220537472617465676973745361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e63654f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820e94b2b8fd98de32dfe8ffdf996c6bf9691663e7573f493e264a8b4d0c4a0f08864736f6c634300050b0032", "devdoc": { "methods": { "approveStrategy(address)": { @@ -1026,19 +1050,19 @@ "pauseRebase()": { "details": "Set the deposit paused flag to true to prevent rebasing." }, - "priceUSDMint(string)": { - "details": "Returns the total price in 18 digit USD for a given asset. Using Min since min is what we use for mint pricing", + "priceUSDMint(address)": { + "details": "Returns the total price in 18 digit USD for a given asset. Never goes above 1, since that is how we price mints", "params": { - "symbol": "String symbol of the asset" + "asset": "address of the asset" }, - "return": "uint256 USD price of 1 of the asset" + "return": "uint256 USD price of 1 of the asset, in 18 decimal fixed" }, - "priceUSDRedeem(string)": { - "details": "Returns the total price in 18 digit USD for a given asset. Using Max since max is what we use for redeem pricing", + "priceUSDRedeem(address)": { + "details": "Returns the total price in 18 digit USD for a given asset. Never goes below 1, since that is how we price redeems", "params": { - "symbol": "String symbol of the asset" + "asset": "Addresss of the asset" }, - "return": "uint256 USD price of 1 of the asset" + "return": "uint256 USD price of 1 of the asset, in 18 decimal fixed" }, "reallocate(address,address,address[],uint256[])": { "params": { @@ -1142,6 +1166,15 @@ }, "unpauseRebase()": { "details": "Set the deposit paused flag to true to allow rebasing." + }, + "withdrawAllFromStrategies()": { + "details": "Withdraws all assets from all the strategies and sends assets to the Vault." + }, + "withdrawAllFromStrategy(address)": { + "details": "Withdraws all assets from the strategy and sends assets to the Vault.", + "params": { + "_strategyAddr": "Strategy address." + } } } }, diff --git a/contracts/deployments/rinkeby/VaultCore.json b/contracts/deployments/rinkeby/VaultCore.json index 4fd6550a85..0eb7883f99 100644 --- a/contracts/deployments/rinkeby/VaultCore.json +++ b/contracts/deployments/rinkeby/VaultCore.json @@ -1,5 +1,5 @@ { - "address": "0x1D6B56e17D08e83dc2198A61Cb5BC9744cF8D9fE", + "address": "0x24203812AcB90c75860db158c637C286259059ba", "abi": [ { "constant": true, @@ -816,42 +816,42 @@ "type": "event" } ], - "transactionHash": "0x91ffd8a6befc2eaffcb917d3f38580d3601d3bcc6851f3890b00664bca3d1330", + "transactionHash": "0x3689f80b2d603cd88b5f7af77b1e9336ccbffdf9f8d205725c393f3fc4b689c2", "receipt": { "to": null, "from": "0xD85A569F3C26f81070544451131c742283360400", - "contractAddress": "0x1D6B56e17D08e83dc2198A61Cb5BC9744cF8D9fE", - "transactionIndex": 2, - "gasUsed": "3252626", - "logsBloom": "0x00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000020000000400000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000010020000000000000000000000000000000000000000400000000000000000000000000", - "blockHash": "0x2b49d1234233b21cfeede6faf85357fc942ce5d110f6ed167388b502415323aa", - "transactionHash": "0x91ffd8a6befc2eaffcb917d3f38580d3601d3bcc6851f3890b00664bca3d1330", + "contractAddress": "0x24203812AcB90c75860db158c637C286259059ba", + "transactionIndex": 5, + "gasUsed": "3142306", + "logsBloom": "0x00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000020000000000000000000000004000000000000000400000000000000000000000000", + "blockHash": "0xbeffa9fba88cc7d1d78222552d454ff94de21ac8b80cd4dc41ff9b9d7d2f02ab", + "transactionHash": "0x3689f80b2d603cd88b5f7af77b1e9336ccbffdf9f8d205725c393f3fc4b689c2", "logs": [ { - "transactionIndex": 2, - "blockNumber": 8010137, - "transactionHash": "0x91ffd8a6befc2eaffcb917d3f38580d3601d3bcc6851f3890b00664bca3d1330", - "address": "0x1D6B56e17D08e83dc2198A61Cb5BC9744cF8D9fE", + "transactionIndex": 5, + "blockNumber": 8292729, + "transactionHash": "0x3689f80b2d603cd88b5f7af77b1e9336ccbffdf9f8d205725c393f3fc4b689c2", + "address": "0x24203812AcB90c75860db158c637C286259059ba", "topics": [ "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000d85a569f3c26f81070544451131c742283360400" ], "data": "0x", - "logIndex": 1, - "blockHash": "0x2b49d1234233b21cfeede6faf85357fc942ce5d110f6ed167388b502415323aa" + "logIndex": 16, + "blockHash": "0xbeffa9fba88cc7d1d78222552d454ff94de21ac8b80cd4dc41ff9b9d7d2f02ab" } ], - "blockNumber": 8010137, - "cumulativeGasUsed": "7391009", + "blockNumber": 8292729, + "cumulativeGasUsed": "3817938", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "c3af786fe12b6b771320281cb59e3482", - "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"redeemFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOusdAmount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultBuffer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllAssets\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getStrategyCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebaseThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"checkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"calculateRedeemOutputs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minimumUnitAmount\",\"type\":\"uint256\"}],\"name\":\"redeemAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumUnitAmount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxSupplyDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"isSupportedAsset\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoAllocateThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAssetCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetDefaultStrategies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"allocate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"priceProvider\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"capitalPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_assets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOusdAmount\",\"type\":\"uint256\"}],\"name\":\"mintMultiple\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImpl\",\"type\":\"address\"}],\"name\":\"setAdminImpl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"AssetSupported\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"AssetDefaultStrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebasePaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebaseUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"VaultBufferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"RedeemFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"PriceProviderUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"AllocateThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"RebaseThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyDiffChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_yield\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"YieldDistribution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"TrusteeFeeBpsChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"TrusteeAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allocate()\":{\"details\":\"Allocate unallocated funds on Vault to strategies.*\"},\"checkBalance(address)\":{\"params\":{\"_asset\":\"Address of asset\"},\"return\":\"uint256 Balance of asset in decimals of asset\"},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"getAllAssets()\":{\"details\":\"Return all asset addresses in order\"},\"getAssetCount()\":{\"details\":\"Return the number of assets suppported by the Vault.\"},\"getStrategyCount()\":{\"details\":\"Return the number of strategies active on the Vault.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"mint(address,uint256,uint256)\":{\"details\":\"Deposit a supported asset and mint OUSD.\",\"params\":{\"_amount\":\"Amount of the asset being deposited\",\"_asset\":\"Address of the asset being deposited\",\"_minimumOusdAmount\":\"Minimum OUSD to mint\"}},\"mintMultiple(address[],uint256[],uint256)\":{\"details\":\"Mint for multiple assets in the same call.\",\"params\":{\"_amounts\":\"Amount of each asset at the same index in the _assets to deposit.\",\"_assets\":\"Addresses of assets being deposited\",\"_minimumOusdAmount\":\"Minimum OUSD to mint\"}},\"rebase()\":{\"details\":\"Calculate the total value of assets held by the Vault and all strategies and update the supply of OUSD.\"},\"redeem(uint256,uint256)\":{\"details\":\"Withdraw a supported asset and burn OUSD.\",\"params\":{\"_amount\":\"Amount of OUSD to burn\",\"_minimumUnitAmount\":\"Minimum stablecoin units to receive in return\"}},\"redeemAll(uint256)\":{\"params\":{\"_minimumUnitAmount\":\"Minimum stablecoin units to receive in return\"}},\"setAdminImpl(address)\":{\"details\":\"set the implementation for the admin, this needs to be in a base class else we cannot set it\",\"params\":{\"newImpl\":\"address of the implementation\"}},\"totalValue()\":{\"details\":\"Determine the total value of assets held by the vault and its strategies.\",\"return\":\"uint256 value Total value in USD (1e18)\"},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}}}},\"userdoc\":{\"methods\":{\"allocate()\":{\"notice\":\"Allocate unallocated funds on Vault to strategies.\"},\"calculateRedeemOutputs(uint256)\":{\"notice\":\"Calculate the outputs for a redeem function, i.e. the mix of coins that will be returned\"},\"checkBalance(address)\":{\"notice\":\"Get the balance of an asset held in Vault and all strategies.\"},\"redeemAll(uint256)\":{\"notice\":\"Withdraw a supported asset and burn all OUSD.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/vault/VaultCore.sol\":\"VaultCore\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"@openzeppelin/upgrades/contracts/Initializable.sol\":{\"content\":\"pragma solidity >=0.4.24 <0.7.0;\\n\\n\\n/**\\n * @title Initializable\\n *\\n * @dev Helper contract to support initializer functions. To use it, replace\\n * the constructor with a function that has the `initializer` modifier.\\n * WARNING: Unlike constructors, initializer functions must be manually\\n * invoked. This applies both to deploying an Initializable contract, as well\\n * as extending an Initializable contract via inheritance.\\n * WARNING: When used with inheritance, manual care must be taken to not invoke\\n * a parent initializer twice, or ensure that all initializers are idempotent,\\n * because this is not dealt with automatically as with constructors.\\n */\\ncontract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to use in the initializer function of a contract.\\n */\\n modifier initializer() {\\n require(initializing || isConstructor() || !initialized, \\\"Contract instance has already been initialized\\\");\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function isConstructor() private view returns (bool) {\\n // extcodesize checks the size of the code stored in an address, and\\n // address returns the current address. Since the code is still not\\n // deployed when running a constructor, any checks on its code size will\\n // yield zero, making it an effective way to detect if a contract is\\n // under construction or not.\\n address self = address(this);\\n uint256 cs;\\n assembly { cs := extcodesize(self) }\\n return cs == 0;\\n }\\n\\n // Reserved storage space to allow for layout changes in the future.\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x9bfec92e36234ecc99b5d37230acb6cd1f99560233753162204104a4897e8721\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x01eab42b6d54fa5389598e0663c24680ecc017e2da848e8ea1c40aeaa8225eef\"},\"contracts/interfaces/IMinMaxOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IMinMaxOracle {\\n //Assuming 8 decimals\\n function priceMin(string calldata symbol) external view returns (uint256);\\n\\n function priceMax(string calldata symbol) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x164c8759ca5a8e39bbe1de6b2504098c543b2f15663c9d452e083418f8313f48\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to Lending platform.\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardToken() external;\\n\\n /**\\n * @dev The address of the reward token for the Strategy.\\n */\\n function rewardTokenAddress() external pure returns (address);\\n\\n /**\\n * @dev The threshold (denominated in the reward token) over which the\\n * vault will auto harvest on allocate calls.\\n */\\n function rewardLiquidationThreshold() external pure returns (uint256);\\n}\\n\",\"keccak256\":\"0xa9ef9546d60635c630e3446f270bc93f34593f5c77db8c671146f6c1eb0b2774\"},\"contracts/interfaces/IVault.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IVault {\\n event AssetSupported(address _asset);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event DepositsPaused();\\n event DepositsUnpaused();\\n\\n // Governable.sol\\n function transferGovernance(address _newGovernor) external;\\n\\n function claimGovernance() external;\\n\\n function governor() external view returns (address);\\n\\n // VaultAdmin.sol\\n function setPriceProvider(address _priceProvider) external;\\n\\n function priceProvider() external view returns (address);\\n\\n function setRedeemFeeBps(uint256 _redeemFeeBps) external;\\n\\n function redeemFeeBps() external view returns (uint256);\\n\\n function setVaultBuffer(uint256 _vaultBuffer) external;\\n\\n function vaultBuffer() external view returns (uint256);\\n\\n function setAutoAllocateThreshold(uint256 _threshold) external;\\n\\n function autoAllocateThreshold() external view returns (uint256);\\n\\n function setRebaseThreshold(uint256 _threshold) external;\\n\\n function rebaseThreshold() external view returns (uint256);\\n\\n function setStrategistAddr(address _address) external;\\n\\n function strategistAddr() external view returns (address);\\n\\n function setUniswapAddr(address _address) external;\\n\\n function uniswapAddr() external view returns (address);\\n\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;\\n\\n function maxSupplyDiff() external view returns (uint256);\\n\\n function setTrusteeAddress(address _address) external;\\n\\n function trusteeAddress() external view returns (address);\\n\\n function setTrusteeFeeBps(uint256 _basis) external;\\n\\n function trusteeFeeBps() external view returns (uint256);\\n\\n function supportAsset(address _asset) external;\\n\\n function approveStrategy(address _addr) external;\\n\\n function removeStrategy(address _addr) external;\\n\\n function setAssetDefaultStrategy(address _asset, address _strategy)\\n external;\\n\\n function assetDefaultStrategies(address _asset)\\n external\\n view\\n returns (address);\\n\\n function pauseRebase() external;\\n\\n function unpauseRebase() external;\\n\\n function rebasePaused() external view returns (bool);\\n\\n function pauseCapital() external;\\n\\n function unpauseCapital() external;\\n\\n function capitalPaused() external view returns (bool);\\n\\n function transferToken(address _asset, uint256 _amount) external;\\n\\n function harvest() external;\\n\\n function harvest(address _strategyAddr) external;\\n\\n function priceUSDMint(string calldata symbol)\\n external\\n view\\n returns (uint256);\\n\\n function priceUSDRedeem(string calldata symbol)\\n external\\n view\\n returns (uint256);\\n\\n // VaultCore.sol\\n function mint(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function mintMultiple(\\n address[] calldata _assets,\\n uint256[] calldata _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount) external;\\n\\n function redeemAll(uint256 _minimumUnitAmount) external;\\n\\n function allocate() external;\\n\\n function reallocate(\\n address _strategyFromAddress,\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external;\\n\\n function rebase() external;\\n\\n function totalValue() external view returns (uint256 value);\\n\\n function checkBalance() external view returns (uint256);\\n\\n function checkBalance(address _asset) external view returns (uint256);\\n\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function getAssetCount() external view returns (uint256);\\n\\n function getAllAssets() external view returns (address[] memory);\\n\\n function getStrategyCount() external view returns (uint256);\\n\\n function isSupportedAsset(address _asset) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x84271ee5504677f7ad8b808df40d16704d5e2b83a9cdb897208d8c7b3e6cb8bb\"},\"contracts/token/OUSD.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {\\n InitializableERC20Detailed\\n} from \\\"../utils/InitializableERC20Detailed.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\n/**\\n * NOTE that this is an ERC20 token but the invariant that the sum of\\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\\n * rebasing design. Any integrations with OUSD should be aware.\\n */\\n\\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n\\n event TotalSupplyUpdated(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n\\n enum RebaseOptions { NotSet, OptOut, OptIn }\\n\\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\\n uint256 public _totalSupply;\\n mapping(address => mapping(address => uint256)) private _allowances;\\n address public vaultAddress = address(0);\\n mapping(address => uint256) private _creditBalances;\\n uint256 public rebasingCredits;\\n uint256 public rebasingCreditsPerToken;\\n // Frozen address/credits are non rebasing (value is held in contracts which\\n // do not receive yield unless they explicitly opt in)\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) public nonRebasingCreditsPerToken;\\n mapping(address => RebaseOptions) public rebaseState;\\n\\n function initialize(\\n string calldata _nameArg,\\n string calldata _symbolArg,\\n address _vaultAddress\\n ) external onlyGovernor initializer {\\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\\n rebasingCreditsPerToken = 1e18;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Savings Manager contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return The total supply of OUSD.\\n */\\n function totalSupply() public view returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the _amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n if (_creditBalances[_account] == 0) return 0;\\n return\\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n return (_creditBalances[_account], _creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the _amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(\\n _value <= balanceOf(msg.sender),\\n \\\"Transfer greater than balance\\\"\\n );\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The _amount of tokens to be transferred.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(_value <= balanceOf(_from), \\\"Transfer greater than balance\\\");\\n\\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\\n _value\\n );\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Update the count of non rebasing credits in response to a transfer\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value Amount of OUSD to transfer\\n */\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\\n\\n // Credits deducted and credited might be different due to the\\n // differing creditsPerToken used by each account\\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\\n\\n _creditBalances[_from] = _creditBalances[_from].sub(\\n creditsDeducted,\\n \\\"Transfer amount exceeds balance\\\"\\n );\\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\\n\\n if (isNonRebasingTo && !isNonRebasingFrom) {\\n // Transfer to non-rebasing account from rebasing account, credits\\n // are removed from the non rebasing tally\\n nonRebasingSupply = nonRebasingSupply.add(_value);\\n // Update rebasingCredits by subtracting the deducted amount\\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\\n // Transfer to rebasing account from non-rebasing account\\n // Decreasing non-rebasing credits by the amount that was sent\\n nonRebasingSupply = nonRebasingSupply.sub(_value);\\n // Update rebasingCredits by adding the credited amount\\n rebasingCredits = rebasingCredits.add(creditsCredited);\\n }\\n }\\n\\n /**\\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n public\\n view\\n returns (uint256)\\n {\\n return _allowances[_owner][_spender];\\n }\\n\\n /**\\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\\n * msg.sender. This method is included for ERC20 compatibility.\\n * increaseAllowance and decreaseAllowance should be used instead.\\n * Changing an allowance with this method brings the risk that someone may transfer both\\n * the old and the new allowance - if they are both greater than zero - if a transfer\\n * transaction is mined before the later approve() call is mined.\\n *\\n * @param _spender The address which will spend the funds.\\n * @param _value The _amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) public returns (bool) {\\n _allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\\n * This method should be used instead of approve() to avoid the double approval vulnerability\\n * described above.\\n * @param _spender The address which will spend the funds.\\n * @param _addedValue The _amount of tokens to increase the allowance by.\\n */\\n function increaseAllowance(address _spender, uint256 _addedValue)\\n public\\n returns (bool)\\n {\\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\\n .add(_addedValue);\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\\n * @param _spender The address which will spend the funds.\\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\\n */\\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\\n public\\n returns (bool)\\n {\\n uint256 oldValue = _allowances[msg.sender][_spender];\\n if (_subtractedValue >= oldValue) {\\n _allowances[msg.sender][_spender] = 0;\\n } else {\\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\\n }\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Mints new tokens, increasing totalSupply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n _mint(_account, _amount);\\n }\\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 * - `to` cannot be the zero address.\\n */\\n function _mint(address _account, uint256 _amount) internal nonReentrant {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\\n\\n // If the account is non rebasing and doesn't have a set creditsPerToken\\n // then set it i.e. this is a mint from a fresh contract\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.add(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.add(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.add(_amount);\\n\\n require(_totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @dev Burns tokens, decreasing totalSupply.\\n */\\n function burn(address account, uint256 amount) external onlyVault {\\n _burn(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 nonReentrant {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n uint256 currentCredits = _creditBalances[_account];\\n\\n // Remove the credits, burning rounding errors\\n if (\\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\\n ) {\\n // Handle dust from rounding\\n _creditBalances[_account] = 0;\\n } else if (currentCredits > creditAmount) {\\n _creditBalances[_account] = _creditBalances[_account].sub(\\n creditAmount\\n );\\n } else {\\n revert(\\\"Remove exceeds balance\\\");\\n }\\n\\n // Remove from the credit tallies and non-rebasing supply\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.sub(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.sub(_amount);\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n if (nonRebasingCreditsPerToken[_account] != 0) {\\n return nonRebasingCreditsPerToken[_account];\\n } else {\\n return rebasingCreditsPerToken;\\n }\\n }\\n\\n /**\\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\\n * Also, ensure contracts are non-rebasing if they have not opted in.\\n * @param _account Address of the account.\\n */\\n function _isNonRebasingAccount(address _account) internal returns (bool) {\\n bool isContract = Address.isContract(_account);\\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\\n _ensureRebasingMigration(_account);\\n }\\n return nonRebasingCreditsPerToken[_account] > 0;\\n }\\n\\n /**\\n * @dev Ensures internal account for rebasing and non-rebasing credits and\\n * supply is updated following deployment of frozen yield change.\\n */\\n function _ensureRebasingMigration(address _account) internal {\\n if (nonRebasingCreditsPerToken[_account] == 0) {\\n // Set fixed credits per token for this account\\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\\n // Update non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\\n // Update credit tallies\\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\\n }\\n }\\n\\n /**\\n * @dev Add a contract address to the non rebasing exception list. I.e. the\\n * address's balance will be part of rebases so the account will be exposed\\n * to upside and downside.\\n */\\n function rebaseOptIn() public nonReentrant {\\n require(_isNonRebasingAccount(msg.sender), \\\"Account has not opted out\\\");\\n\\n // Convert balance into the same amount at the current exchange rate\\n uint256 newCreditBalance = _creditBalances[msg.sender]\\n .mul(rebasingCreditsPerToken)\\n .div(_creditsPerToken(msg.sender));\\n\\n // Decreasing non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\\n\\n _creditBalances[msg.sender] = newCreditBalance;\\n\\n // Increase rebasing credits, totalSupply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\\n\\n rebaseState[msg.sender] = RebaseOptions.OptIn;\\n\\n // Delete any fixed credits per token\\n delete nonRebasingCreditsPerToken[msg.sender];\\n }\\n\\n /**\\n * @dev Remove a contract address to the non rebasing exception list.\\n */\\n function rebaseOptOut() public nonReentrant {\\n require(!_isNonRebasingAccount(msg.sender), \\\"Account has not opted in\\\");\\n\\n // Increase non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\\n // Set fixed credits per token\\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\\n\\n // Decrease rebasing credits, total supply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\\n\\n // Mark explicitly opted out of rebasing\\n rebaseState[msg.sender] = RebaseOptions.OptOut;\\n }\\n\\n /**\\n * @dev Modify the supply without minting new tokens. This uses a change in\\n * the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n * @return uint256 representing the new total supply.\\n */\\n function changeSupply(uint256 _newTotalSupply)\\n external\\n onlyVault\\n nonReentrant\\n {\\n require(_totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (_totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n return;\\n }\\n\\n _totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\\n _totalSupply.sub(nonRebasingSupply)\\n );\\n\\n require(rebasingCreditsPerToken > 0, \\\"Invalid change in supply\\\");\\n\\n _totalSupply = rebasingCredits\\n .divPrecisely(rebasingCreditsPerToken)\\n .add(nonRebasingSupply);\\n\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n }\\n}\\n\",\"keccak256\":\"0xea89a8b152b363982ba8db340b1e20c3194b2e75a06630cbbf43e3c50fff61a4\"},\"contracts/utils/Helpers.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0xd2ca92e0af883dc1aec5b22caced274e59829e0e30a9e955dcc48b8d921f5cdc\"},\"contracts/utils/InitializableERC20Detailed.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/**\\n * @dev Optional functions from the ERC20 standard.\\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\\n */\\ncontract InitializableERC20Detailed is IERC20 {\\n // Storage gap to skip storage from prior to OUSD reset\\n uint256[100] private _____gap;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\\n * these values are immutable: they can only be set once during\\n * construction.\\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\\n */\\n function _initialize(\\n string memory nameArg,\\n string memory symbolArg,\\n uint8 decimalsArg\\n ) internal {\\n _name = nameArg;\\n _symbol = symbolArg;\\n _decimals = decimalsArg;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view 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 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.\\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 returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x7919369d0f3bd74b4f0ee78a682afe43f91b186cdd0708e303068e4feeb29007\"},\"contracts/utils/StableMath.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n// Based on StableMath from Stability Labs Pty. Ltd.\\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\\n\\nlibrary StableMath {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Scaling unit for use in specific calculations,\\n * where 1 * 10**18, or 1e18 represents a unit '1'\\n */\\n uint256 private constant FULL_SCALE = 1e18;\\n\\n /***************************************\\n Helpers\\n ****************************************/\\n\\n /**\\n * @dev Adjust the scale of an integer\\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\\n */\\n function scaleBy(uint256 x, int8 adjustment)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (adjustment > 0) {\\n x = x.mul(10**uint256(adjustment));\\n } else if (adjustment < 0) {\\n x = x.div(10**uint256(adjustment * -1));\\n }\\n return x;\\n }\\n\\n /***************************************\\n Precise Arithmetic\\n ****************************************/\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\\n return mulTruncateScale(x, y, FULL_SCALE);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @param scale Scale unit\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncateScale(\\n uint256 x,\\n uint256 y,\\n uint256 scale\\n ) internal pure returns (uint256) {\\n // e.g. assume scale = fullScale\\n // z = 10e18 * 9e17 = 9e36\\n uint256 z = x.mul(y);\\n // return 9e38 / 1e18 = 9e18\\n return z.div(scale);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit, rounded up to the closest base unit.\\n */\\n function mulTruncateCeil(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e17 * 17268172638 = 138145381104e17\\n uint256 scaled = x.mul(y);\\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\\n return ceil.div(FULL_SCALE);\\n }\\n\\n /**\\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\\n * @param x Left hand input to division\\n * @param y Right hand input to division\\n * @return Result after multiplying the left operand by the scale, and\\n * executing the division on the right hand input.\\n */\\n function divPrecisely(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e18 * 1e18 = 8e36\\n uint256 z = x.mul(FULL_SCALE);\\n // e.g. 8e36 / 10e18 = 8e17\\n return z.div(y);\\n }\\n}\\n\",\"keccak256\":\"0xa77fccf850feb6d54ba3a6530f92554caef8a67a1ceb573d4f8a5d1bf64ff9d2\"},\"contracts/vault/VaultCore.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Vault Contract\\n * @notice The Vault contract stores assets. On a deposit, OUSD will be minted\\n and sent to the depositor. On a withdrawal, OUSD will be burned and\\n assets will be sent to the withdrawer. The Vault accepts deposits of\\n interest form yield bearing strategies which will modify the supply\\n of OUSD.\\n * @author Origin Protocol Inc\\n */\\n\\nimport \\\"./VaultStorage.sol\\\";\\nimport { IMinMaxOracle } from \\\"../interfaces/IMinMaxOracle.sol\\\";\\nimport { IVault } from \\\"../interfaces/IVault.sol\\\";\\n\\ncontract VaultCore is VaultStorage {\\n uint256 constant MAX_UINT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\\n\\n /**\\n * @dev Verifies that the rebasing is not paused.\\n */\\n modifier whenNotRebasePaused() {\\n require(!rebasePaused, \\\"Rebasing paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Verifies that the deposits are not paused.\\n */\\n modifier whenNotCapitalPaused() {\\n require(!capitalPaused, \\\"Capital paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Deposit a supported asset and mint OUSD.\\n * @param _asset Address of the asset being deposited\\n * @param _amount Amount of the asset being deposited\\n * @param _minimumOusdAmount Minimum OUSD to mint\\n */\\n function mint(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external whenNotCapitalPaused nonReentrant {\\n require(assets[_asset].isSupported, \\\"Asset is not supported\\\");\\n require(_amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n uint256 price = IMinMaxOracle(priceProvider).priceMin(\\n Helpers.getSymbol(_asset)\\n );\\n if (price > 1e8) {\\n price = 1e8;\\n }\\n uint256 assetDecimals = Helpers.getDecimals(_asset);\\n uint256 unitAdjustedDeposit = _amount.scaleBy(int8(18 - assetDecimals));\\n uint256 priceAdjustedDeposit = _amount.mulTruncateScale(\\n price.scaleBy(int8(10)), // 18-8 because oracles have 8 decimals precision\\n 10**assetDecimals\\n );\\n\\n if (_minimumOusdAmount > 0) {\\n require(\\n priceAdjustedDeposit >= _minimumOusdAmount,\\n \\\"Mint amount lower than minimum\\\"\\n );\\n }\\n\\n emit Mint(msg.sender, priceAdjustedDeposit);\\n\\n // Rebase must happen before any transfers occur.\\n if (unitAdjustedDeposit >= rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n\\n // Mint matching OUSD\\n oUSD.mint(msg.sender, priceAdjustedDeposit);\\n\\n // Transfer the deposited coins to the vault\\n IERC20 asset = IERC20(_asset);\\n asset.safeTransferFrom(msg.sender, address(this), _amount);\\n\\n if (unitAdjustedDeposit >= autoAllocateThreshold) {\\n _allocate();\\n }\\n }\\n\\n /**\\n * @dev Mint for multiple assets in the same call.\\n * @param _assets Addresses of assets being deposited\\n * @param _amounts Amount of each asset at the same index in the _assets\\n * to deposit.\\n * @param _minimumOusdAmount Minimum OUSD to mint\\n */\\n function mintMultiple(\\n address[] calldata _assets,\\n uint256[] calldata _amounts,\\n uint256 _minimumOusdAmount\\n ) external whenNotCapitalPaused nonReentrant {\\n require(_assets.length == _amounts.length, \\\"Parameter length mismatch\\\");\\n\\n uint256 unitAdjustedTotal = 0;\\n uint256 priceAdjustedTotal = 0;\\n uint256[] memory assetPrices = _getAssetPrices(false);\\n for (uint256 j = 0; j < _assets.length; j++) {\\n // In memoriam\\n require(assets[_assets[j]].isSupported, \\\"Asset is not supported\\\");\\n require(_amounts[j] > 0, \\\"Amount must be greater than 0\\\");\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n if (_assets[j] == allAssets[i]) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n uint256 price = assetPrices[i];\\n if (price > 1e18) {\\n price = 1e18;\\n }\\n unitAdjustedTotal = unitAdjustedTotal.add(\\n _amounts[j].scaleBy(int8(18 - assetDecimals))\\n );\\n priceAdjustedTotal = priceAdjustedTotal.add(\\n _amounts[j].mulTruncateScale(price, 10**assetDecimals)\\n );\\n }\\n }\\n }\\n\\n if (_minimumOusdAmount > 0) {\\n require(\\n priceAdjustedTotal >= _minimumOusdAmount,\\n \\\"Mint amount lower than minimum\\\"\\n );\\n }\\n\\n emit Mint(msg.sender, priceAdjustedTotal);\\n\\n // Rebase must happen before any transfers occur.\\n if (unitAdjustedTotal >= rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n\\n oUSD.mint(msg.sender, priceAdjustedTotal);\\n\\n for (uint256 i = 0; i < _assets.length; i++) {\\n IERC20 asset = IERC20(_assets[i]);\\n asset.safeTransferFrom(msg.sender, address(this), _amounts[i]);\\n }\\n\\n if (unitAdjustedTotal >= autoAllocateThreshold) {\\n _allocate();\\n }\\n }\\n\\n /**\\n * @dev Withdraw a supported asset and burn OUSD.\\n * @param _amount Amount of OUSD to burn\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount)\\n public\\n whenNotCapitalPaused\\n nonReentrant\\n {\\n if (_amount > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n _redeem(_amount, _minimumUnitAmount);\\n }\\n\\n /**\\n * @dev Withdraw a supported asset and burn OUSD.\\n * @param _amount Amount of OUSD to burn\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function _redeem(uint256 _amount, uint256 _minimumUnitAmount) internal {\\n require(_amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n uint256 _totalSupply = oUSD.totalSupply();\\n uint256 _backingValue = _totalValue();\\n\\n if (maxSupplyDiff > 0) {\\n // Allow a max difference of maxSupplyDiff% between\\n // backing assets value and OUSD total supply\\n uint256 diff = _totalSupply.divPrecisely(_backingValue);\\n\\n require(\\n (diff > 1e18 ? diff.sub(1e18) : uint256(1e18).sub(diff)) <=\\n maxSupplyDiff,\\n \\\"Backing supply liquidity error\\\"\\n );\\n }\\n\\n emit Redeem(msg.sender, _amount);\\n\\n // Calculate redemption outputs\\n uint256[] memory outputs = _calculateRedeemOutputs(_amount);\\n // Send outputs\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n if (outputs[i] == 0) continue;\\n\\n IERC20 asset = IERC20(allAssets[i]);\\n\\n if (asset.balanceOf(address(this)) >= outputs[i]) {\\n // Use Vault funds first if sufficient\\n asset.safeTransfer(msg.sender, outputs[i]);\\n } else {\\n address strategyAddr = assetDefaultStrategies[allAssets[i]];\\n if (strategyAddr != address(0)) {\\n // Nothing in Vault, but something in Strategy, send from there\\n IStrategy strategy = IStrategy(strategyAddr);\\n strategy.withdraw(msg.sender, allAssets[i], outputs[i]);\\n } else {\\n // Cant find funds anywhere\\n revert(\\\"Liquidity error\\\");\\n }\\n }\\n }\\n\\n if (_minimumUnitAmount > 0) {\\n uint256 unitTotal = 0;\\n for (uint256 i = 0; i < outputs.length; i++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n unitTotal = unitTotal.add(\\n outputs[i].scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n require(\\n unitTotal >= _minimumUnitAmount,\\n \\\"Redeem amount lower than minimum\\\"\\n );\\n }\\n\\n oUSD.burn(msg.sender, _amount);\\n\\n // Until we can prove that we won't affect the prices of our assets\\n // by withdrawing them, this should be here.\\n // It's possible that a strategy was off on its asset total, perhaps\\n // a reward token sold for more or for less than anticipated.\\n if (_amount > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n }\\n\\n /**\\n * @notice Withdraw a supported asset and burn all OUSD.\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function redeemAll(uint256 _minimumUnitAmount)\\n external\\n whenNotCapitalPaused\\n nonReentrant\\n {\\n // Unfortunately we have to do balanceOf twice, the rebase may change\\n // the account balance\\n if (oUSD.balanceOf(msg.sender) > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n _redeem(oUSD.balanceOf(msg.sender), _minimumUnitAmount);\\n }\\n\\n /**\\n * @notice Allocate unallocated funds on Vault to strategies.\\n * @dev Allocate unallocated funds on Vault to strategies.\\n **/\\n function allocate() public whenNotCapitalPaused nonReentrant {\\n _allocate();\\n }\\n\\n /**\\n * @notice Allocate unallocated funds on Vault to strategies.\\n * @dev Allocate unallocated funds on Vault to strategies.\\n **/\\n function _allocate() internal {\\n uint256 vaultValue = _totalValueInVault();\\n // Nothing in vault to allocate\\n if (vaultValue == 0) return;\\n uint256 strategiesValue = _totalValueInStrategies();\\n // We have a method that does the same as this, gas optimisation\\n uint256 calculatedTotalValue = vaultValue.add(strategiesValue);\\n\\n // We want to maintain a buffer on the Vault so calculate a percentage\\n // modifier to multiply each amount being allocated by to enforce the\\n // vault buffer\\n uint256 vaultBufferModifier;\\n if (strategiesValue == 0) {\\n // Nothing in Strategies, allocate 100% minus the vault buffer to\\n // strategies\\n vaultBufferModifier = uint256(1e18).sub(vaultBuffer);\\n } else {\\n vaultBufferModifier = vaultBuffer.mul(calculatedTotalValue).div(\\n vaultValue\\n );\\n if (1e18 > vaultBufferModifier) {\\n // E.g. 1e18 - (1e17 * 10e18)/5e18 = 8e17\\n // (5e18 * 8e17) / 1e18 = 4e18 allocated from Vault\\n vaultBufferModifier = uint256(1e18).sub(vaultBufferModifier);\\n } else {\\n // We need to let the buffer fill\\n return;\\n }\\n }\\n if (vaultBufferModifier == 0) return;\\n\\n // Iterate over all assets in the Vault and allocate the the appropriate\\n // strategy\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n IERC20 asset = IERC20(allAssets[i]);\\n uint256 assetBalance = asset.balanceOf(address(this));\\n // No balance, nothing to do here\\n if (assetBalance == 0) continue;\\n\\n // Multiply the balance by the vault buffer modifier and truncate\\n // to the scale of the asset decimals\\n uint256 allocateAmount = assetBalance.mulTruncate(\\n vaultBufferModifier\\n );\\n\\n address depositStrategyAddr = assetDefaultStrategies[address(\\n asset\\n )];\\n\\n if (depositStrategyAddr != address(0) && allocateAmount > 0) {\\n IStrategy strategy = IStrategy(depositStrategyAddr);\\n // Transfer asset to Strategy and call deposit method to\\n // mint or take required action\\n asset.safeTransfer(address(strategy), allocateAmount);\\n strategy.deposit(address(asset), allocateAmount);\\n }\\n }\\n\\n // Harvest for all reward tokens above reward liquidation threshold\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n address rewardTokenAddress = strategy.rewardTokenAddress();\\n if (rewardTokenAddress != address(0)) {\\n uint256 liquidationThreshold = strategy\\n .rewardLiquidationThreshold();\\n if (liquidationThreshold == 0) {\\n // No threshold set, always harvest from strategy\\n IVault(address(this)).harvest(allStrategies[i]);\\n } else {\\n // Check balance against liquidation threshold\\n // Note some strategies don't hold the reward token balance\\n // on their contract so the liquidation threshold should be\\n // set to 0\\n IERC20 rewardToken = IERC20(rewardTokenAddress);\\n uint256 rewardTokenAmount = rewardToken.balanceOf(\\n allStrategies[i]\\n );\\n if (rewardTokenAmount >= liquidationThreshold) {\\n IVault(address(this)).harvest(allStrategies[i]);\\n }\\n }\\n }\\n }\\n }\\n\\n /**\\n * @dev Calculate the total value of assets held by the Vault and all\\n * strategies and update the supply of OUSD.\\n */\\n function rebase() public whenNotRebasePaused nonReentrant {\\n _rebase();\\n }\\n\\n /**\\n * @dev Calculate the total value of assets held by the Vault and all\\n * strategies and update the supply of OUSD, optionaly sending a\\n * portion of the yield to the trustee.\\n */\\n function _rebase() internal whenNotRebasePaused {\\n uint256 ousdSupply = oUSD.totalSupply();\\n if (ousdSupply == 0) {\\n return;\\n }\\n uint256 vaultValue = _totalValue();\\n\\n // Yield fee collection\\n address _trusteeAddress = trusteeAddress; // gas savings\\n if (_trusteeAddress != address(0) && (vaultValue > ousdSupply)) {\\n uint256 yield = vaultValue.sub(ousdSupply);\\n uint256 fee = yield.mul(trusteeFeeBps).div(10000);\\n require(yield > fee, \\\"Fee must not be greater than yield\\\");\\n if (fee > 0) {\\n oUSD.mint(_trusteeAddress, fee);\\n }\\n emit YieldDistribution(_trusteeAddress, yield, fee);\\n }\\n\\n // Only rachet OUSD supply upwards\\n ousdSupply = oUSD.totalSupply(); // Final check should use latest value\\n if (vaultValue > ousdSupply) {\\n oUSD.changeSupply(vaultValue);\\n }\\n }\\n\\n /**\\n * @dev Determine the total value of assets held by the vault and its\\n * strategies.\\n * @return uint256 value Total value in USD (1e18)\\n */\\n function totalValue() external view returns (uint256 value) {\\n value = _totalValue();\\n }\\n\\n /**\\n * @dev Internal Calculate the total value of the assets held by the\\n * vault and its strategies.\\n * @return uint256 value Total value in USD (1e18)\\n */\\n function _totalValue() internal view returns (uint256 value) {\\n return _totalValueInVault().add(_totalValueInStrategies());\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held in Vault.\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInVault() internal view returns (uint256 value) {\\n for (uint256 y = 0; y < allAssets.length; y++) {\\n IERC20 asset = IERC20(allAssets[y]);\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\\n uint256 balance = asset.balanceOf(address(this));\\n if (balance > 0) {\\n value = value.add(balance.scaleBy(int8(18 - assetDecimals)));\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held in Strategies.\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInStrategies() internal view returns (uint256 value) {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n value = value.add(_totalValueInStrategy(allStrategies[i]));\\n }\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held by strategy.\\n * @param _strategyAddr Address of the strategy\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInStrategy(address _strategyAddr)\\n internal\\n view\\n returns (uint256 value)\\n {\\n IStrategy strategy = IStrategy(_strategyAddr);\\n for (uint256 y = 0; y < allAssets.length; y++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\\n if (strategy.supportsAsset(allAssets[y])) {\\n uint256 balance = strategy.checkBalance(allAssets[y]);\\n if (balance > 0) {\\n value = value.add(\\n balance.scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Get the balance of an asset held in Vault and all strategies.\\n * @param _asset Address of asset\\n * @return uint256 Balance of asset in decimals of asset\\n */\\n function checkBalance(address _asset) external view returns (uint256) {\\n return _checkBalance(_asset);\\n }\\n\\n /**\\n * @notice Get the balance of an asset held in Vault and all strategies.\\n * @param _asset Address of asset\\n * @return uint256 Balance of asset in decimals of asset\\n */\\n function _checkBalance(address _asset)\\n internal\\n view\\n returns (uint256 balance)\\n {\\n IERC20 asset = IERC20(_asset);\\n balance = asset.balanceOf(address(this));\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n if (strategy.supportsAsset(_asset)) {\\n balance = balance.add(strategy.checkBalance(_asset));\\n }\\n }\\n }\\n\\n /**\\n * @notice Get the balance of all assets held in Vault and all strategies.\\n * @return uint256 Balance of all assets (1e18)\\n */\\n function _checkBalance() internal view returns (uint256 balance) {\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n balance = balance.add(\\n _checkBalance(allAssets[i]).scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n }\\n\\n /**\\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\\n * coins that will be returned\\n */\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory)\\n {\\n return _calculateRedeemOutputs(_amount);\\n }\\n\\n /**\\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\\n * coins that will be returned.\\n * @return Array of amounts respective to the supported assets\\n */\\n function _calculateRedeemOutputs(uint256 _amount)\\n internal\\n view\\n returns (uint256[] memory outputs)\\n {\\n // We always give out coins in proportion to how many we have,\\n // Now if all coins were the same value, this math would easy,\\n // just take the percentage of each coin, and multiply by the\\n // value to be given out. But if coins are worth more than $1,\\n // then we would end up handing out too many coins. We need to\\n // adjust by the total value of coins.\\n //\\n // To do this, we total up the value of our coins, by their\\n // percentages. Then divide what we would otherwise give out by\\n // this number.\\n //\\n // Let say we have 100 DAI at $1.06 and 200 USDT at $1.00.\\n // So for every 1 DAI we give out, we'll be handing out 2 USDT\\n // Our total output ratio is: 33% * 1.06 + 66% * 1.00 = 1.02\\n //\\n // So when calculating the output, we take the percentage of\\n // each coin, times the desired output value, divided by the\\n // totalOutputRatio.\\n //\\n // For example, withdrawing: 30 OUSD:\\n // DAI 33% * 30 / 1.02 = 9.80 DAI\\n // USDT = 66 % * 30 / 1.02 = 19.60 USDT\\n //\\n // Checking these numbers:\\n // 9.80 DAI * 1.06 = $10.40\\n // 19.60 USDT * 1.00 = $19.60\\n //\\n // And so the user gets $10.40 + $19.60 = $30 worth of value.\\n\\n uint256 assetCount = getAssetCount();\\n uint256[] memory assetPrices = _getAssetPrices(true);\\n uint256[] memory assetBalances = new uint256[](assetCount);\\n uint256[] memory assetDecimals = new uint256[](assetCount);\\n uint256 totalBalance = 0;\\n uint256 totalOutputRatio = 0;\\n outputs = new uint256[](assetCount);\\n\\n // Calculate redeem fee\\n if (redeemFeeBps > 0) {\\n uint256 redeemFee = _amount.mul(redeemFeeBps).div(10000);\\n _amount = _amount.sub(redeemFee);\\n }\\n\\n // Calculate assets balances and decimals once,\\n // for a large gas savings.\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 balance = _checkBalance(allAssets[i]);\\n uint256 decimals = Helpers.getDecimals(allAssets[i]);\\n assetBalances[i] = balance;\\n assetDecimals[i] = decimals;\\n totalBalance = totalBalance.add(\\n balance.scaleBy(int8(18 - decimals))\\n );\\n }\\n // Calculate totalOutputRatio\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 price = assetPrices[i];\\n // Never give out more than one\\n // stablecoin per dollar of OUSD\\n if (price < 1e18) {\\n price = 1e18;\\n }\\n uint256 ratio = assetBalances[i]\\n .scaleBy(int8(18 - assetDecimals[i]))\\n .mul(price)\\n .div(totalBalance);\\n totalOutputRatio = totalOutputRatio.add(ratio);\\n }\\n // Calculate final outputs\\n uint256 factor = _amount.divPrecisely(totalOutputRatio);\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n outputs[i] = assetBalances[i].mul(factor).div(totalBalance);\\n }\\n }\\n\\n /**\\n * @notice Get an array of the supported asset prices in USD.\\n * @return uint256[] Array of asset prices in USD (1e18)\\n */\\n function _getAssetPrices(bool useMax)\\n internal\\n view\\n returns (uint256[] memory assetPrices)\\n {\\n assetPrices = new uint256[](getAssetCount());\\n\\n IMinMaxOracle oracle = IMinMaxOracle(priceProvider);\\n // Price from Oracle is returned with 8 decimals\\n // _amount is in assetDecimals\\n\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n string memory symbol = Helpers.getSymbol(allAssets[i]);\\n // Get all the USD prices of the asset in 1e18\\n if (useMax) {\\n assetPrices[i] = oracle.priceMax(symbol).scaleBy(int8(18 - 8));\\n } else {\\n assetPrices[i] = oracle.priceMin(symbol).scaleBy(int8(18 - 8));\\n }\\n }\\n }\\n\\n /***************************************\\n Utils\\n ****************************************/\\n\\n /**\\n * @dev Return the number of assets suppported by the Vault.\\n */\\n function getAssetCount() public view returns (uint256) {\\n return allAssets.length;\\n }\\n\\n /**\\n * @dev Return all asset addresses in order\\n */\\n function getAllAssets() external view returns (address[] memory) {\\n return allAssets;\\n }\\n\\n /**\\n * @dev Return the number of strategies active on the Vault.\\n */\\n function getStrategyCount() external view returns (uint256) {\\n return allStrategies.length;\\n }\\n\\n function isSupportedAsset(address _asset) external view returns (bool) {\\n return assets[_asset].isSupported;\\n }\\n\\n /**\\n * @dev Falldown to the admin implementation\\n * @notice This is a catch all for all functions not declared in core\\n */\\n function() external payable {\\n bytes32 slot = adminImplPosition;\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize)\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas, sload(slot), 0, calldatasize, 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize)\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize)\\n }\\n default {\\n return(0, returndatasize)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9af2d88c824d11589927a4f7c1f60157ead5ca26352a4171139ece27a3b5b22d\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD VaultStorage Contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\n\\ncontract VaultStorage is Initializable, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n using SafeMath for int256;\\n using SafeERC20 for IERC20;\\n\\n event AssetSupported(address _asset);\\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\\n event PriceProviderUpdated(address _priceProvider);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event UniswapUpdated(address _address);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n\\n // Assets supported by the Vault, i.e. Stablecoins\\n struct Asset {\\n bool isSupported;\\n }\\n mapping(address => Asset) assets;\\n address[] allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n mapping(address => Strategy) strategies;\\n address[] allStrategies;\\n\\n // Address of the Oracle price provider contract\\n address public priceProvider;\\n // Pausing bools\\n bool public rebasePaused = false;\\n bool public capitalPaused = true;\\n // Redemption fee in basis points\\n uint256 public redeemFeeBps;\\n // Buffer of assets to keep in Vault to handle (most) withdrawals\\n uint256 public vaultBuffer;\\n // Mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n // Mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n OUSD oUSD;\\n\\n //keccak256(\\\"OUSD.vault.governor.admin.impl\\\");\\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\\n\\n // Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n // Address of Uniswap\\n address public uniswapAddr = address(0);\\n\\n // Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n // Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n mapping(address => address) public assetDefaultStrategies;\\n\\n uint256 public maxSupplyDiff;\\n\\n // Trustee address that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n // Amount of yield collected in basis points\\n uint256 public trusteeFeeBps;\\n\\n /**\\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\\n * @param newImpl address of the implementation\\n */\\n function setAdminImpl(address newImpl) external onlyGovernor {\\n require(\\n Address.isContract(newImpl),\\n \\\"new implementation is not a contract\\\"\\n );\\n bytes32 position = adminImplPosition;\\n assembly {\\n sstore(position, newImpl)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x02d224b70c086a3df5cf22792721aed5f278ddf4bc7b98b67ac9c38c767760a0\"}},\"version\":1}", - "bytecode": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b600080516020620039e783398151915255565b600080516020620039e78339815191525490565b6138f580620000f26000396000f3fe6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610b33565b3480156102ed57600080fd5b50610233610b39565b34801561030257600080fd5b5061030b610b3f565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610ba1565b34801561037c57600080fd5b5061025a610ba7565b34801561039157600080fd5b50610233610bb6565b3480156103a657600080fd5b506103af610bbc565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610bcc565b3480156103e457600080fd5b506102ca610bdb565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610c3d565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610c4e565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610c59565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610e29565b3480156104b057600080fd5b50610233610f10565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610f16565b3480156104f857600080fd5b50610233610f34565b34801561050d57600080fd5b50610233610f3a565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610f40565b34801561055557600080fd5b506102ca610f5b565b34801561056a57600080fd5b506102ca611016565b34801561057f57600080fd5b5061025a6110cb565b34801561059457600080fd5b506103af6110da565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b03166110fd565b3480156105dc57600080fd5b506102336111a9565b3480156105f157600080fd5b506103af6111b3565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b9193509150356111c3565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b03166116be565b60385481565b600061070c61177f565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b7833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b6037546000906001600160a01b03166319af6bf06108a4886117a4565b6040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156108f05781810151838201526020016108d8565b50505050905090810190601f16801561091d5780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b15801561093a57600080fd5b505afa15801561094e573d6000803e3d6000fd5b505050506040513d602081101561096457600080fd5b505190506305f5e10081111561097b57506305f5e1005b6000610986876118d5565b9050600061099e87601284900363ffffffff61198f16565b905060006109c86109b685600a63ffffffff61198f16565b8990600a86900a63ffffffff6119e916565b90508615610a255786811015610a25576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a7c5750603754600160a01b900460ff16155b15610a8957610a89611a17565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610adc57600080fd5b505af1158015610af0573d6000803e3d6000fd5b508b9250610b129150506001600160a01b03821633308c63ffffffff611d3e16565b603a548310610b2357610b23611d9e565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b9757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b79575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610be36122c1565b6001600160a01b0316336001600160a01b031614610c325760405162461bcd60e51b81526004018080602001828103825260308152602001806138916030913960400191505060405180910390fd5b610c3b336122e6565b565b6000610c4882612394565b92915050565b6060610c4882612555565b603754600160a81b900460ff1615610ca9576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415610d01576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b54603c54604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610d5357600080fd5b505afa158015610d67573d6000803e3d6000fd5b505050506040513d6020811015610d7d57600080fd5b5051118015610d965750603754600160a01b900460ff16155b15610da357610da3611a17565b603c54604080516370a0823160e01b81523360048201529051610e21926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d6020811015610e1957600080fd5b505184612816565b506001905550565b603754600160a81b900460ff1615610e79576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415610ed1576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b5484118015610ef05750603754600160a01b900460ff16155b15610efd57610efd611a17565b610f078484612816565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610fab576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415611003576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561100f611d9e565b5060019055565b603754600160a01b900460ff1615611067576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206137b7833981519152805460028114156110bf576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561100f611a17565b6037546001600160a01b031681565b60006110e461177f565b6001600160a01b0316336001600160a01b031614905090565b6111056110da565b611156576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61115f81612dc0565b806001600160a01b031661117161177f565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612de4565b603754600160a81b900460ff1681565b603754600160a81b900460ff1615611213576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b78339815191528054600281141561126b576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282558584146112c3576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b60008060606112d182612e05565b905060005b8981101561150a57603360008c8c848181106112ee57fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff1661135e576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061136c57fe5b90506020020135116113c5576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b60345481101561150157603481815481106113df57fe5b6000918252602090912001546001600160a01b03168c8c8481811061140057fe5b905060200201356001600160a01b03166001600160a01b031614156114f957600061144b6034838154811061143157fe5b6000918252602090912001546001600160a01b03166118d5565b9050600084838151811061145b57fe5b60200260200101519050670de0b6b3a76400008111156114805750670de0b6b3a76400005b6114b86114ab836012038e8e8881811061149657fe5b9050602002013561198f90919063ffffffff16565b889063ffffffff61300b16565b96506114f46114e78284600a0a8f8f898181106114d157fe5b905060200201356119e99092919063ffffffff16565b879063ffffffff61300b16565b955050505b6001016113c8565b506001016112d6565b5085156115665785821015611566576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b5483101580156115bd5750603754600160a01b900460ff16155b156115ca576115ca611a17565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b15801561161d57600080fd5b505af1158015611631573d6000803e3d6000fd5b506000925050505b8981101561169c5760008b8b8381811061164f57fe5b905060200201356001600160a01b0316905061169333308c8c8681811061167257fe5b90506020020135846001600160a01b0316611d3e909392919063ffffffff16565b50600101611639565b50603a5483106116ae576116ae611d9e565b5050506001825550505050505050565b6116c66110da565b611717576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6117208161306c565b61175b5760405162461bcd60e51b81526004018080602001828103825260248152602001806137d76024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606080826001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b1580156117e057600080fd5b505afa1580156117f4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561181d57600080fd5b810190808051604051939291908464010000000082111561183d57600080fd5b90830190602082018581111561185257600080fd5b825164010000000081118282018810171561186c57600080fd5b82525081516020918201929091019080838360005b83811015611899578181015183820152602001611881565b50505050905090810190601f1680156118c65780820380516001836020036101000a031916815260200191505b50604052509195945050505050565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561191157600080fd5b505afa158015611925573d6000803e3d6000fd5b505050506040513d602081101561193b57600080fd5b505160ff16905060048110801590611954575060128111155b610c485760405162461bcd60e51b81526004018080602001828103825260298152602001806137fb6029913960400191505060405180910390fd5b6000808260000b13156119ba576119b383600084900b600a0a63ffffffff6130a816565b92506119e2565b60008260000b12156119e2576119df836000848103900b600a0a63ffffffff61310116565b92505b5090919050565b6000806119fc858563ffffffff6130a816565b9050611a0e818463ffffffff61310116565b95945050505050565b603754600160a01b900460ff1615611a68576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015611aad57600080fd5b505afa158015611ac1573d6000803e3d6000fd5b505050506040513d6020811015611ad757600080fd5b5051905080611ae65750610c3b565b6000611af0612de4565b6042549091506001600160a01b03168015801590611b0d57508282115b15611c4f576000611b24838563ffffffff61314316565b90506000611b4f612710611b43604354856130a890919063ffffffff16565b9063ffffffff61310116565b9050808211611b8f5760405162461bcd60e51b81526004018080602001828103825260228152602001806138456022913960400191505060405180910390fd5b8015611c0357603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9d57600080fd5b505afa158015611cb1573d6000803e3d6000fd5b505050506040513d6020811015611cc757600080fd5b5051925082821115611d3957603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611d2057600080fd5b505af1158015611d34573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611d98908590613185565b50505050565b6000611da861333d565b905080611db55750610c3b565b6000611dbf61342d565b90506000611dd3838363ffffffff61300b16565b9050600082611dff57603954611df890670de0b6b3a76400009063ffffffff61314316565b9050611e4b565b611e1884611b43846039546130a890919063ffffffff16565b905080670de0b6b3a76400001115611e4257611df8670de0b6b3a76400008263ffffffff61314316565b50505050610c3b565b80611e595750505050610c3b565b60005b603454811015611fe857600060348281548110611e7557fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611ec857600080fd5b505afa158015611edc573d6000803e3d6000fd5b505050506040513d6020811015611ef257600080fd5b5051905080611f02575050611fe0565b6000611f14828663ffffffff61347f16565b6001600160a01b03808516600090815260406020819052902054919250168015801590611f415750600082115b15611fdb5780611f616001600160a01b038616828563ffffffff61349416565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611fc157600080fd5b505af1158015611fd5573d6000803e3d6000fd5b50505050505b505050505b600101611e5c565b5060005b6036548110156122ba5760006036828154811061200557fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b15801561205257600080fd5b505afa158015612066573d6000803e3d6000fd5b505050506040513d602081101561207c57600080fd5b505190506001600160a01b038116156122b0576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b1580156120ca57600080fd5b505afa1580156120de573d6000803e3d6000fd5b505050506040513d60208110156120f457600080fd5b505190508061218357306001600160a01b0316630e5c011e6036868154811061211957fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561216657600080fd5b505af115801561217a573d6000803e3d6000fd5b505050506122ae565b60008290506000816001600160a01b03166370a08231603688815481106121a657fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156121f457600080fd5b505afa158015612208573d6000803e3d6000fd5b505050506040513d602081101561221e57600080fd5b505190508281106122ab57306001600160a01b0316630e5c011e6036888154811061224557fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561229257600080fd5b505af11580156122a6573d6000803e3d6000fd5b505050505b50505b505b5050600101611fec565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116612341576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661235361177f565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3612391816134e6565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156123df57600080fd5b505afa1580156123f3573d6000803e3d6000fd5b505050506040513d602081101561240957600080fd5b5051915060005b60365481101561254e5760006036828154811061242957fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561247f57600080fd5b505afa158015612493573d6000803e3d6000fd5b505050506040513d60208110156124a957600080fd5b50511561254557612542816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561250957600080fd5b505afa15801561251d573d6000803e3d6000fd5b505050506040513d602081101561253357600080fd5b5051859063ffffffff61300b16565b93505b50600101612410565b5050919050565b60606000612561610f3a565b9050606061256f6001612e05565b905060608260405190808252806020026020018201604052801561259d578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156125cc578160200160208202803883390190505b5060408051868152602080880282010190915290915060009081908680156125fe578160200160208202803883390190505b506038549097501561263d576000612627612710611b436038548c6130a890919063ffffffff16565b9050612639898263ffffffff61314316565b9850505b60005b6034548110156126ed5760006126766034838154811061265c57fe5b6000918252602090912001546001600160a01b0316612394565b9050600061268a6034848154811061143157fe5b90508187848151811061269957fe5b602002602001018181525050808684815181106126b257fe5b60209081029190910101526126e16126d483601284900363ffffffff61198f16565b869063ffffffff61300b16565b94505050600101612640565b5060005b60345481101561279e57600086828151811061270957fe5b60200260200101519050670de0b6b3a764000081101561272e5750670de0b6b3a76400005b600061278085611b43846127748a888151811061274757fe5b60200260200101516012038c898151811061275e57fe5b602002602001015161198f90919063ffffffff16565b9063ffffffff6130a816565b9050612792848263ffffffff61300b16565b935050506001016126f1565b5060006127b1898363ffffffff61350a16565b905060005b603454811015612809576127ea84611b43848985815181106127d457fe5b60200260200101516130a890919063ffffffff16565b8982815181106127f657fe5b60209081029190910101526001016127b6565b5050505050505050919050565b6000821161286b576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b1580156128b057600080fd5b505afa1580156128c4573d6000803e3d6000fd5b505050506040513d60208110156128da57600080fd5b5051905060006128e8612de4565b604154909150156129a3576000612905838363ffffffff61350a16565b9050604154670de0b6b3a7640000821161293657612931670de0b6b3a76400008363ffffffff61314316565b61294e565b61294e82670de0b6b3a764000063ffffffff61314316565b11156129a1576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810186905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160606129e985612555565b905060005b603454811015612c7f57818181518110612a0457fe5b602002602001015160001415612a1957612c77565b600060348281548110612a2857fe5b60009182526020909120015483516001600160a01b039091169150839083908110612a4f57fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015612aad57600080fd5b505afa158015612ac1573d6000803e3d6000fd5b505050506040513d6020811015612ad757600080fd5b505110612b1457612b0f33848481518110612aee57fe5b6020026020010151836001600160a01b03166134949092919063ffffffff16565b612c75565b60006040600060348581548110612b2757fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612c34576000819050806001600160a01b031663d9caed123360348781548110612b7c57fe5b9060005260206000200160009054906101000a90046001600160a01b0316888881518110612ba657fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612c1657600080fd5b505af1158015612c2a573d6000803e3d6000fd5b5050505050612c73565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b6001016129ee565b508315612d2d576000805b8251811015612cd5576000612ca56034838154811061143157fe5b9050612cca612cbd8260120386858151811061275e57fe5b849063ffffffff61300b16565b925050600101612c8a565b5084811015612d2b576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612d8057600080fd5b505af1158015612d94573d6000803e3d6000fd5b50505050603b5485118015612db35750603754600160a01b900460ff16155b156122ba576122ba611a17565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612df161342d565b612df961333d565b9063ffffffff61300b16565b6060612e0f610f3a565b604051908082528060200260200182016040528015612e38578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561254e576060612e8160348381548110612e6757fe5b6000918252602090912001546001600160a01b03166117a4565b90508415612f8957612f6c600a846001600160a01b0316637bf0c215846040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612eea578181015183820152602001612ed2565b50505050905090810190601f168015612f175780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b158015612f3457600080fd5b505afa158015612f48573d6000803e3d6000fd5b505050506040513d6020811015612f5e57600080fd5b50519063ffffffff61198f16565b848381518110612f7857fe5b602002602001018181525050613002565b60405163019af6bf60e41b8152602060048201818152835160248401528351612fe993600a936001600160a01b038916936319af6bf093889391928392604401919085019080838360008315612eea578181015183820152602001612ed2565b848381518110612ff557fe5b6020026020010181815250505b50600101612e4b565b600082820183811015613065576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906130a057508115155b949350505050565b6000826130b757506000610c48565b828202828482816130c457fe5b04146130655760405162461bcd60e51b81526004018080602001828103825260218152602001806138246021913960400191505060405180910390fd5b600061306583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613537565b600061306583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506135d9565b613197826001600160a01b031661306c565b6131e8576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106132265780518252601f199092019160209182019101613207565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613288576040519150601f19603f3d011682016040523d82523d6000602084013e61328d565b606091505b5091509150816132e4576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611d985780806020019051602081101561330057600080fd5b5051611d985760405162461bcd60e51b815260040180806020018281038252602a815260200180613867602a913960400191505060405180910390fd5b6000805b6034548110156134295760006034828154811061335a57fe5b6000918252602082200154603480546001600160a01b039092169350613384918590811061143157fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156133d057600080fd5b505afa1580156133e4573d6000803e3d6000fd5b505050506040513d60208110156133fa57600080fd5b50519050801561341e5761341b6126d482601285900363ffffffff61198f16565b94505b505050600101613341565b5090565b6000805b603654811015613429576134756134686036838154811061344e57fe5b6000918252602090912001546001600160a01b0316613633565b839063ffffffff61300b16565b9150600101613431565b60006130658383670de0b6b3a76400006119e9565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611d39908490613185565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061352584670de0b6b3a764000063ffffffff6130a816565b90506130a0818463ffffffff61310116565b600081836135c35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613588578181015183820152602001613570565b50505050905090810190601f1680156135b55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816135cf57fe5b0495945050505050565b6000818484111561362b5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613588578181015183820152602001613570565b505050900390565b600081815b60345481101561254e5760006136546034838154811061143157fe5b9050826001600160a01b031663aa388af66034848154811061367257fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156136c057600080fd5b505afa1580156136d4573d6000803e3d6000fd5b505050506040513d60208110156136ea57600080fd5b5051156137ad576000836001600160a01b0316635f5152266034858154811061370f57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561375d57600080fd5b505afa158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5051905080156137ab576137a86126d482601285900363ffffffff61198f16565b94505b505b5060010161363856fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158209a486e46973c6f28f9c4d92884e27d910324137adbdaefaaa0cbbf675447effe64736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", - "deployedBytecode": "0x6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610b33565b3480156102ed57600080fd5b50610233610b39565b34801561030257600080fd5b5061030b610b3f565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610ba1565b34801561037c57600080fd5b5061025a610ba7565b34801561039157600080fd5b50610233610bb6565b3480156103a657600080fd5b506103af610bbc565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610bcc565b3480156103e457600080fd5b506102ca610bdb565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610c3d565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610c4e565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610c59565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610e29565b3480156104b057600080fd5b50610233610f10565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610f16565b3480156104f857600080fd5b50610233610f34565b34801561050d57600080fd5b50610233610f3a565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610f40565b34801561055557600080fd5b506102ca610f5b565b34801561056a57600080fd5b506102ca611016565b34801561057f57600080fd5b5061025a6110cb565b34801561059457600080fd5b506103af6110da565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b03166110fd565b3480156105dc57600080fd5b506102336111a9565b3480156105f157600080fd5b506103af6111b3565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b9193509150356111c3565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b03166116be565b60385481565b600061070c61177f565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b7833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b6037546000906001600160a01b03166319af6bf06108a4886117a4565b6040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156108f05781810151838201526020016108d8565b50505050905090810190601f16801561091d5780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b15801561093a57600080fd5b505afa15801561094e573d6000803e3d6000fd5b505050506040513d602081101561096457600080fd5b505190506305f5e10081111561097b57506305f5e1005b6000610986876118d5565b9050600061099e87601284900363ffffffff61198f16565b905060006109c86109b685600a63ffffffff61198f16565b8990600a86900a63ffffffff6119e916565b90508615610a255786811015610a25576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a7c5750603754600160a01b900460ff16155b15610a8957610a89611a17565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610adc57600080fd5b505af1158015610af0573d6000803e3d6000fd5b508b9250610b129150506001600160a01b03821633308c63ffffffff611d3e16565b603a548310610b2357610b23611d9e565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b9757602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b79575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610be36122c1565b6001600160a01b0316336001600160a01b031614610c325760405162461bcd60e51b81526004018080602001828103825260308152602001806138916030913960400191505060405180910390fd5b610c3b336122e6565b565b6000610c4882612394565b92915050565b6060610c4882612555565b603754600160a81b900460ff1615610ca9576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415610d01576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b54603c54604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610d5357600080fd5b505afa158015610d67573d6000803e3d6000fd5b505050506040513d6020811015610d7d57600080fd5b5051118015610d965750603754600160a01b900460ff16155b15610da357610da3611a17565b603c54604080516370a0823160e01b81523360048201529051610e21926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d6020811015610e1957600080fd5b505184612816565b506001905550565b603754600160a81b900460ff1615610e79576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415610ed1576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b5484118015610ef05750603754600160a01b900460ff16155b15610efd57610efd611a17565b610f078484612816565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610fab576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b783398151915280546002811415611003576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561100f611d9e565b5060019055565b603754600160a01b900460ff1615611067576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206137b7833981519152805460028114156110bf576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561100f611a17565b6037546001600160a01b031681565b60006110e461177f565b6001600160a01b0316336001600160a01b031614905090565b6111056110da565b611156576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61115f81612dc0565b806001600160a01b031661117161177f565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612de4565b603754600160a81b900460ff1681565b603754600160a81b900460ff1615611213576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206137b78339815191528054600281141561126b576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282558584146112c3576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b60008060606112d182612e05565b905060005b8981101561150a57603360008c8c848181106112ee57fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff1661135e576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061136c57fe5b90506020020135116113c5576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b60345481101561150157603481815481106113df57fe5b6000918252602090912001546001600160a01b03168c8c8481811061140057fe5b905060200201356001600160a01b03166001600160a01b031614156114f957600061144b6034838154811061143157fe5b6000918252602090912001546001600160a01b03166118d5565b9050600084838151811061145b57fe5b60200260200101519050670de0b6b3a76400008111156114805750670de0b6b3a76400005b6114b86114ab836012038e8e8881811061149657fe5b9050602002013561198f90919063ffffffff16565b889063ffffffff61300b16565b96506114f46114e78284600a0a8f8f898181106114d157fe5b905060200201356119e99092919063ffffffff16565b879063ffffffff61300b16565b955050505b6001016113c8565b506001016112d6565b5085156115665785821015611566576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b5483101580156115bd5750603754600160a01b900460ff16155b156115ca576115ca611a17565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b15801561161d57600080fd5b505af1158015611631573d6000803e3d6000fd5b506000925050505b8981101561169c5760008b8b8381811061164f57fe5b905060200201356001600160a01b0316905061169333308c8c8681811061167257fe5b90506020020135846001600160a01b0316611d3e909392919063ffffffff16565b50600101611639565b50603a5483106116ae576116ae611d9e565b5050506001825550505050505050565b6116c66110da565b611717576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6117208161306c565b61175b5760405162461bcd60e51b81526004018080602001828103825260248152602001806137d76024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b606080826001600160a01b03166395d89b416040518163ffffffff1660e01b815260040160006040518083038186803b1580156117e057600080fd5b505afa1580156117f4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561181d57600080fd5b810190808051604051939291908464010000000082111561183d57600080fd5b90830190602082018581111561185257600080fd5b825164010000000081118282018810171561186c57600080fd5b82525081516020918201929091019080838360005b83811015611899578181015183820152602001611881565b50505050905090810190601f1680156118c65780820380516001836020036101000a031916815260200191505b50604052509195945050505050565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561191157600080fd5b505afa158015611925573d6000803e3d6000fd5b505050506040513d602081101561193b57600080fd5b505160ff16905060048110801590611954575060128111155b610c485760405162461bcd60e51b81526004018080602001828103825260298152602001806137fb6029913960400191505060405180910390fd5b6000808260000b13156119ba576119b383600084900b600a0a63ffffffff6130a816565b92506119e2565b60008260000b12156119e2576119df836000848103900b600a0a63ffffffff61310116565b92505b5090919050565b6000806119fc858563ffffffff6130a816565b9050611a0e818463ffffffff61310116565b95945050505050565b603754600160a01b900460ff1615611a68576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015611aad57600080fd5b505afa158015611ac1573d6000803e3d6000fd5b505050506040513d6020811015611ad757600080fd5b5051905080611ae65750610c3b565b6000611af0612de4565b6042549091506001600160a01b03168015801590611b0d57508282115b15611c4f576000611b24838563ffffffff61314316565b90506000611b4f612710611b43604354856130a890919063ffffffff16565b9063ffffffff61310116565b9050808211611b8f5760405162461bcd60e51b81526004018080602001828103825260228152602001806138456022913960400191505060405180910390fd5b8015611c0357603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611bea57600080fd5b505af1158015611bfe573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c9d57600080fd5b505afa158015611cb1573d6000803e3d6000fd5b505050506040513d6020811015611cc757600080fd5b5051925082821115611d3957603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611d2057600080fd5b505af1158015611d34573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611d98908590613185565b50505050565b6000611da861333d565b905080611db55750610c3b565b6000611dbf61342d565b90506000611dd3838363ffffffff61300b16565b9050600082611dff57603954611df890670de0b6b3a76400009063ffffffff61314316565b9050611e4b565b611e1884611b43846039546130a890919063ffffffff16565b905080670de0b6b3a76400001115611e4257611df8670de0b6b3a76400008263ffffffff61314316565b50505050610c3b565b80611e595750505050610c3b565b60005b603454811015611fe857600060348281548110611e7557fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611ec857600080fd5b505afa158015611edc573d6000803e3d6000fd5b505050506040513d6020811015611ef257600080fd5b5051905080611f02575050611fe0565b6000611f14828663ffffffff61347f16565b6001600160a01b03808516600090815260406020819052902054919250168015801590611f415750600082115b15611fdb5780611f616001600160a01b038616828563ffffffff61349416565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611fc157600080fd5b505af1158015611fd5573d6000803e3d6000fd5b50505050505b505050505b600101611e5c565b5060005b6036548110156122ba5760006036828154811061200557fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b15801561205257600080fd5b505afa158015612066573d6000803e3d6000fd5b505050506040513d602081101561207c57600080fd5b505190506001600160a01b038116156122b0576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b1580156120ca57600080fd5b505afa1580156120de573d6000803e3d6000fd5b505050506040513d60208110156120f457600080fd5b505190508061218357306001600160a01b0316630e5c011e6036868154811061211957fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561216657600080fd5b505af115801561217a573d6000803e3d6000fd5b505050506122ae565b60008290506000816001600160a01b03166370a08231603688815481106121a657fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156121f457600080fd5b505afa158015612208573d6000803e3d6000fd5b505050506040513d602081101561221e57600080fd5b505190508281106122ab57306001600160a01b0316630e5c011e6036888154811061224557fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561229257600080fd5b505af11580156122a6573d6000803e3d6000fd5b505050505b50505b505b5050600101611fec565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116612341576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661235361177f565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3612391816134e6565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156123df57600080fd5b505afa1580156123f3573d6000803e3d6000fd5b505050506040513d602081101561240957600080fd5b5051915060005b60365481101561254e5760006036828154811061242957fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561247f57600080fd5b505afa158015612493573d6000803e3d6000fd5b505050506040513d60208110156124a957600080fd5b50511561254557612542816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561250957600080fd5b505afa15801561251d573d6000803e3d6000fd5b505050506040513d602081101561253357600080fd5b5051859063ffffffff61300b16565b93505b50600101612410565b5050919050565b60606000612561610f3a565b9050606061256f6001612e05565b905060608260405190808252806020026020018201604052801561259d578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156125cc578160200160208202803883390190505b5060408051868152602080880282010190915290915060009081908680156125fe578160200160208202803883390190505b506038549097501561263d576000612627612710611b436038548c6130a890919063ffffffff16565b9050612639898263ffffffff61314316565b9850505b60005b6034548110156126ed5760006126766034838154811061265c57fe5b6000918252602090912001546001600160a01b0316612394565b9050600061268a6034848154811061143157fe5b90508187848151811061269957fe5b602002602001018181525050808684815181106126b257fe5b60209081029190910101526126e16126d483601284900363ffffffff61198f16565b869063ffffffff61300b16565b94505050600101612640565b5060005b60345481101561279e57600086828151811061270957fe5b60200260200101519050670de0b6b3a764000081101561272e5750670de0b6b3a76400005b600061278085611b43846127748a888151811061274757fe5b60200260200101516012038c898151811061275e57fe5b602002602001015161198f90919063ffffffff16565b9063ffffffff6130a816565b9050612792848263ffffffff61300b16565b935050506001016126f1565b5060006127b1898363ffffffff61350a16565b905060005b603454811015612809576127ea84611b43848985815181106127d457fe5b60200260200101516130a890919063ffffffff16565b8982815181106127f657fe5b60209081029190910101526001016127b6565b5050505050505050919050565b6000821161286b576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b1580156128b057600080fd5b505afa1580156128c4573d6000803e3d6000fd5b505050506040513d60208110156128da57600080fd5b5051905060006128e8612de4565b604154909150156129a3576000612905838363ffffffff61350a16565b9050604154670de0b6b3a7640000821161293657612931670de0b6b3a76400008363ffffffff61314316565b61294e565b61294e82670de0b6b3a764000063ffffffff61314316565b11156129a1576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810186905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160606129e985612555565b905060005b603454811015612c7f57818181518110612a0457fe5b602002602001015160001415612a1957612c77565b600060348281548110612a2857fe5b60009182526020909120015483516001600160a01b039091169150839083908110612a4f57fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015612aad57600080fd5b505afa158015612ac1573d6000803e3d6000fd5b505050506040513d6020811015612ad757600080fd5b505110612b1457612b0f33848481518110612aee57fe5b6020026020010151836001600160a01b03166134949092919063ffffffff16565b612c75565b60006040600060348581548110612b2757fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612c34576000819050806001600160a01b031663d9caed123360348781548110612b7c57fe5b9060005260206000200160009054906101000a90046001600160a01b0316888881518110612ba657fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612c1657600080fd5b505af1158015612c2a573d6000803e3d6000fd5b5050505050612c73565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b6001016129ee565b508315612d2d576000805b8251811015612cd5576000612ca56034838154811061143157fe5b9050612cca612cbd8260120386858151811061275e57fe5b849063ffffffff61300b16565b925050600101612c8a565b5084811015612d2b576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612d8057600080fd5b505af1158015612d94573d6000803e3d6000fd5b50505050603b5485118015612db35750603754600160a01b900460ff16155b156122ba576122ba611a17565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612df161342d565b612df961333d565b9063ffffffff61300b16565b6060612e0f610f3a565b604051908082528060200260200182016040528015612e38578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561254e576060612e8160348381548110612e6757fe5b6000918252602090912001546001600160a01b03166117a4565b90508415612f8957612f6c600a846001600160a01b0316637bf0c215846040518263ffffffff1660e01b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612eea578181015183820152602001612ed2565b50505050905090810190601f168015612f175780820380516001836020036101000a031916815260200191505b509250505060206040518083038186803b158015612f3457600080fd5b505afa158015612f48573d6000803e3d6000fd5b505050506040513d6020811015612f5e57600080fd5b50519063ffffffff61198f16565b848381518110612f7857fe5b602002602001018181525050613002565b60405163019af6bf60e41b8152602060048201818152835160248401528351612fe993600a936001600160a01b038916936319af6bf093889391928392604401919085019080838360008315612eea578181015183820152602001612ed2565b848381518110612ff557fe5b6020026020010181815250505b50600101612e4b565b600082820183811015613065576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906130a057508115155b949350505050565b6000826130b757506000610c48565b828202828482816130c457fe5b04146130655760405162461bcd60e51b81526004018080602001828103825260218152602001806138246021913960400191505060405180910390fd5b600061306583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613537565b600061306583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506135d9565b613197826001600160a01b031661306c565b6131e8576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106132265780518252601f199092019160209182019101613207565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613288576040519150601f19603f3d011682016040523d82523d6000602084013e61328d565b606091505b5091509150816132e4576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611d985780806020019051602081101561330057600080fd5b5051611d985760405162461bcd60e51b815260040180806020018281038252602a815260200180613867602a913960400191505060405180910390fd5b6000805b6034548110156134295760006034828154811061335a57fe5b6000918252602082200154603480546001600160a01b039092169350613384918590811061143157fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156133d057600080fd5b505afa1580156133e4573d6000803e3d6000fd5b505050506040513d60208110156133fa57600080fd5b50519050801561341e5761341b6126d482601285900363ffffffff61198f16565b94505b505050600101613341565b5090565b6000805b603654811015613429576134756134686036838154811061344e57fe5b6000918252602090912001546001600160a01b0316613633565b839063ffffffff61300b16565b9150600101613431565b60006130658383670de0b6b3a76400006119e9565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611d39908490613185565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061352584670de0b6b3a764000063ffffffff6130a816565b90506130a0818463ffffffff61310116565b600081836135c35760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613588578181015183820152602001613570565b50505050905090810190601f1680156135b55780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816135cf57fe5b0495945050505050565b6000818484111561362b5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315613588578181015183820152602001613570565b505050900390565b600081815b60345481101561254e5760006136546034838154811061143157fe5b9050826001600160a01b031663aa388af66034848154811061367257fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156136c057600080fd5b505afa1580156136d4573d6000803e3d6000fd5b505050506040513d60208110156136ea57600080fd5b5051156137ad576000836001600160a01b0316635f5152266034858154811061370f57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561375d57600080fd5b505afa158015613771573d6000803e3d6000fd5b505050506040513d602081101561378757600080fd5b5051905080156137ab576137a86126d482601285900363ffffffff61198f16565b94505b505b5060010161363856fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158209a486e46973c6f28f9c4d92884e27d910324137adbdaefaaa0cbbf675447effe64736f6c634300050b0032", + "solcInputHash": "86605db9d81ca0a1790de251140fb0d9", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"redeemFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"uniswapAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOusdAmount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultBuffer\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeFeeBps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAllAssets\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getStrategyCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"trusteeAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebaseThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasePaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"checkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"calculateRedeemOutputs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_minimumUnitAmount\",\"type\":\"uint256\"}],\"name\":\"redeemAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_minimumUnitAmount\",\"type\":\"uint256\"}],\"name\":\"redeem\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"maxSupplyDiff\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"isSupportedAsset\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"autoAllocateThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"getAssetCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetDefaultStrategies\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"allocate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebase\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"priceProvider\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalValue\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"capitalPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_assets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_amounts\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256\",\"name\":\"_minimumOusdAmount\",\"type\":\"uint256\"}],\"name\":\"mintMultiple\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImpl\",\"type\":\"address\"}],\"name\":\"setAdminImpl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"AssetSupported\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_strategy\",\"type\":\"address\"}],\"name\":\"AssetDefaultStrategyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"}],\"name\":\"StrategyRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Mint\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Redeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapitalUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebasePaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"RebaseUnpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_vaultBuffer\",\"type\":\"uint256\"}],\"name\":\"VaultBufferUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_redeemFeeBps\",\"type\":\"uint256\"}],\"name\":\"RedeemFeeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_priceProvider\",\"type\":\"address\"}],\"name\":\"PriceProviderUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"AllocateThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_threshold\",\"type\":\"uint256\"}],\"name\":\"RebaseThresholdUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"UniswapUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxSupplyDiff\",\"type\":\"uint256\"}],\"name\":\"MaxSupplyDiffChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_yield\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"YieldDistribution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_basis\",\"type\":\"uint256\"}],\"name\":\"TrusteeFeeBpsChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"TrusteeAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allocate()\":{\"details\":\"Allocate unallocated funds on Vault to strategies.*\"},\"checkBalance(address)\":{\"params\":{\"_asset\":\"Address of asset\"},\"return\":\"uint256 Balance of asset in decimals of asset\"},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"getAllAssets()\":{\"details\":\"Return all asset addresses in order\"},\"getAssetCount()\":{\"details\":\"Return the number of assets suppported by the Vault.\"},\"getStrategyCount()\":{\"details\":\"Return the number of strategies active on the Vault.\"},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"mint(address,uint256,uint256)\":{\"details\":\"Deposit a supported asset and mint OUSD.\",\"params\":{\"_amount\":\"Amount of the asset being deposited\",\"_asset\":\"Address of the asset being deposited\",\"_minimumOusdAmount\":\"Minimum OUSD to mint\"}},\"mintMultiple(address[],uint256[],uint256)\":{\"details\":\"Mint for multiple assets in the same call.\",\"params\":{\"_amounts\":\"Amount of each asset at the same index in the _assets to deposit.\",\"_assets\":\"Addresses of assets being deposited\",\"_minimumOusdAmount\":\"Minimum OUSD to mint\"}},\"rebase()\":{\"details\":\"Calculate the total value of assets held by the Vault and all strategies and update the supply of OUSD.\"},\"redeem(uint256,uint256)\":{\"details\":\"Withdraw a supported asset and burn OUSD.\",\"params\":{\"_amount\":\"Amount of OUSD to burn\",\"_minimumUnitAmount\":\"Minimum stablecoin units to receive in return\"}},\"redeemAll(uint256)\":{\"params\":{\"_minimumUnitAmount\":\"Minimum stablecoin units to receive in return\"}},\"setAdminImpl(address)\":{\"details\":\"set the implementation for the admin, this needs to be in a base class else we cannot set it\",\"params\":{\"newImpl\":\"address of the implementation\"}},\"totalValue()\":{\"details\":\"Determine the total value of assets held by the vault and its strategies.\",\"return\":\"uint256 value Total value in USD (1e18)\"},\"transferGovernance(address)\":{\"details\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\",\"params\":{\"_newGovernor\":\"Address of the new Governor\"}}}},\"userdoc\":{\"methods\":{\"allocate()\":{\"notice\":\"Allocate unallocated funds on Vault to strategies.\"},\"calculateRedeemOutputs(uint256)\":{\"notice\":\"Calculate the outputs for a redeem function, i.e. the mix of coins that will be returned\"},\"checkBalance(address)\":{\"notice\":\"Get the balance of an asset held in Vault and all strategies.\"},\"redeemAll(uint256)\":{\"notice\":\"Withdraw a supported asset and burn all OUSD.\"}}}},\"settings\":{\"compilationTarget\":{\"contracts/vault/VaultCore.sol\":\"VaultCore\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n * - Subtraction cannot overflow.\\n *\\n * _Available since v2.4.0._\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n // Solidity only automatically asserts when dividing by 0\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n * - The divisor cannot be zero.\\n *\\n * _Available since v2.4.0._\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x640b6dee7a4b830bdfd52b5031a07fc2b12209f5b2e29e5d364a7d37f69d8076\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {ERC20Detailed}.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0xe5bb0f57cff3e299f360052ba50f1ea0fff046df2be070b6943e0e3c3fdad8a9\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.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 ERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function callOptionalReturn(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.\\n\\n // A Solidity high level call has three parts:\\n // 1. The target address is checked to verify it contains contract code\\n // 2. The call itself is made, and success asserted\\n // 3. The return value is decoded, which in turn checks the size of the returned data.\\n // solhint-disable-next-line max-line-length\\n require(address(token).isContract(), \\\"SafeERC20: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = address(token).call(data);\\n require(success, \\\"SafeERC20: low-level call failed\\\");\\n\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x6f2c9955d65c522b80f4b8792f076512d2df947d2112cbc4d98a4781ed42ede2\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"pragma solidity ^0.5.5;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following \\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\\n // for accounts without code, i.e. `keccak256('')`\\n bytes32 codehash;\\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { codehash := extcodehash(account) }\\n return (codehash != accountHash && codehash != 0x0);\\n }\\n\\n /**\\n * @dev Converts an `address` into `address payable`. Note that this is\\n * simply a type cast: the actual underlying value is not changed.\\n *\\n * _Available since v2.4.0._\\n */\\n function toPayable(address account) internal pure returns (address payable) {\\n return address(uint160(account));\\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 * _Available since v2.4.0._\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-call-value\\n (bool success, ) = recipient.call.value(amount)(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n}\\n\",\"keccak256\":\"0x1a8e5072509c5ea7365eb1d48030b9be865140c8fb779968da0a459a0e174a11\"},\"@openzeppelin/upgrades/contracts/Initializable.sol\":{\"content\":\"pragma solidity >=0.4.24 <0.7.0;\\n\\n\\n/**\\n * @title Initializable\\n *\\n * @dev Helper contract to support initializer functions. To use it, replace\\n * the constructor with a function that has the `initializer` modifier.\\n * WARNING: Unlike constructors, initializer functions must be manually\\n * invoked. This applies both to deploying an Initializable contract, as well\\n * as extending an Initializable contract via inheritance.\\n * WARNING: When used with inheritance, manual care must be taken to not invoke\\n * a parent initializer twice, or ensure that all initializers are idempotent,\\n * because this is not dealt with automatically as with constructors.\\n */\\ncontract Initializable {\\n\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to use in the initializer function of a contract.\\n */\\n modifier initializer() {\\n require(initializing || isConstructor() || !initialized, \\\"Contract instance has already been initialized\\\");\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n /// @dev Returns true if and only if the function is running in the constructor\\n function isConstructor() private view returns (bool) {\\n // extcodesize checks the size of the code stored in an address, and\\n // address returns the current address. Since the code is still not\\n // deployed when running a constructor, any checks on its code size will\\n // yield zero, making it an effective way to detect if a contract is\\n // under construction or not.\\n address self = address(this);\\n uint256 cs;\\n assembly { cs := extcodesize(self) }\\n return cs == 0;\\n }\\n\\n // Reserved storage space to allow for layout changes in the future.\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x9bfec92e36234ecc99b5d37230acb6cd1f99560233753162204104a4897e8721\"},\"contracts/governance/Governable.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Governable Contract\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\ncontract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32\\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32\\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32\\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial Governor.\\n */\\n constructor() internal {\\n _setGovernor(msg.sender);\\n emit GovernorshipTransferred(address(0), _governor());\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @dev Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n bytes32 position = governorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and make it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n assembly {\\n sstore(position, _ENTERED)\\n }\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n emit GovernorshipTransferred(_governor(), _newGovernor);\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0x3e51ea48102945bf4b305bf9722a07514a585a29555d92f8c84352d1a4cfcee1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x01eab42b6d54fa5389598e0663c24680ecc017e2da848e8ea1c40aeaa8225eef\"},\"contracts/interfaces/IBuyback.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IBuyback {\\n function swap() external;\\n}\\n\",\"keccak256\":\"0xb85059a081297a310ede87d1eb30356d3c938e97488a99d1de0c65ebf26dc92d\"},\"contracts/interfaces/IOracle.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IOracle {\\n /**\\n * @dev returns the asset price in USD, 8 decimal digits.\\n */\\n function price(address asset) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x7ddbe1f9ed76feb2fbd52ecfe449e17ef67f7edd5616c6a1eda92a84baa1190f\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to platform\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Deposit the entire balance of all supported assets in the Strategy\\n * to the platform\\n */\\n function depositAll() external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardToken() external;\\n\\n /**\\n * @dev The address of the reward token for the Strategy.\\n */\\n function rewardTokenAddress() external pure returns (address);\\n\\n /**\\n * @dev The threshold (denominated in the reward token) over which the\\n * vault will auto harvest on allocate calls.\\n */\\n function rewardLiquidationThreshold() external pure returns (uint256);\\n}\\n\",\"keccak256\":\"0xe03dc1c97ad3677296da9a7e1e5f708abd227d1147f6f220c5cc8f23c1cd87e0\"},\"contracts/interfaces/IVault.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\ninterface IVault {\\n event AssetSupported(address _asset);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event DepositsPaused();\\n event DepositsUnpaused();\\n\\n // Governable.sol\\n function transferGovernance(address _newGovernor) external;\\n\\n function claimGovernance() external;\\n\\n function governor() external view returns (address);\\n\\n // VaultAdmin.sol\\n function setPriceProvider(address _priceProvider) external;\\n\\n function priceProvider() external view returns (address);\\n\\n function setRedeemFeeBps(uint256 _redeemFeeBps) external;\\n\\n function redeemFeeBps() external view returns (uint256);\\n\\n function setVaultBuffer(uint256 _vaultBuffer) external;\\n\\n function vaultBuffer() external view returns (uint256);\\n\\n function setAutoAllocateThreshold(uint256 _threshold) external;\\n\\n function autoAllocateThreshold() external view returns (uint256);\\n\\n function setRebaseThreshold(uint256 _threshold) external;\\n\\n function rebaseThreshold() external view returns (uint256);\\n\\n function setStrategistAddr(address _address) external;\\n\\n function strategistAddr() external view returns (address);\\n\\n function setUniswapAddr(address _address) external;\\n\\n function uniswapAddr() external view returns (address);\\n\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;\\n\\n function maxSupplyDiff() external view returns (uint256);\\n\\n function setTrusteeAddress(address _address) external;\\n\\n function trusteeAddress() external view returns (address);\\n\\n function setTrusteeFeeBps(uint256 _basis) external;\\n\\n function trusteeFeeBps() external view returns (uint256);\\n\\n function supportAsset(address _asset) external;\\n\\n function approveStrategy(address _addr) external;\\n\\n function removeStrategy(address _addr) external;\\n\\n function setAssetDefaultStrategy(address _asset, address _strategy)\\n external;\\n\\n function assetDefaultStrategies(address _asset)\\n external\\n view\\n returns (address);\\n\\n function pauseRebase() external;\\n\\n function unpauseRebase() external;\\n\\n function rebasePaused() external view returns (bool);\\n\\n function pauseCapital() external;\\n\\n function unpauseCapital() external;\\n\\n function capitalPaused() external view returns (bool);\\n\\n function transferToken(address _asset, uint256 _amount) external;\\n\\n function harvest() external;\\n\\n function harvest(address _strategyAddr) external;\\n\\n function priceUSDMint(address asset) external view returns (uint256);\\n\\n function priceUSDRedeem(address asset) external view returns (uint256);\\n\\n function withdrawAllFromStrategy(address _strategyAddr) external;\\n\\n function withdrawAllFromStrategies() external;\\n\\n // VaultCore.sol\\n function mint(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function mintMultiple(\\n address[] calldata _assets,\\n uint256[] calldata _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount) external;\\n\\n function redeemAll(uint256 _minimumUnitAmount) external;\\n\\n function allocate() external;\\n\\n function reallocate(\\n address _strategyFromAddress,\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external;\\n\\n function rebase() external;\\n\\n function totalValue() external view returns (uint256 value);\\n\\n function checkBalance() external view returns (uint256);\\n\\n function checkBalance(address _asset) external view returns (uint256);\\n\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function getAssetCount() external view returns (uint256);\\n\\n function getAllAssets() external view returns (address[] memory);\\n\\n function getStrategyCount() external view returns (uint256);\\n\\n function isSupportedAsset(address _asset) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x3bf6745000b68ce59f9083d9f005cbe84853c4688acbdc7d37ebbba3dae8bdbc\"},\"contracts/token/OUSD.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport {\\n InitializableERC20Detailed\\n} from \\\"../utils/InitializableERC20Detailed.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\n\\n/**\\n * NOTE that this is an ERC20 token but the invariant that the sum of\\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\\n * rebasing design. Any integrations with OUSD should be aware.\\n */\\n\\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n\\n event TotalSupplyUpdated(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n\\n enum RebaseOptions { NotSet, OptOut, OptIn }\\n\\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\\n uint256 public _totalSupply;\\n mapping(address => mapping(address => uint256)) private _allowances;\\n address public vaultAddress = address(0);\\n mapping(address => uint256) private _creditBalances;\\n uint256 public rebasingCredits;\\n uint256 public rebasingCreditsPerToken;\\n // Frozen address/credits are non rebasing (value is held in contracts which\\n // do not receive yield unless they explicitly opt in)\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) public nonRebasingCreditsPerToken;\\n mapping(address => RebaseOptions) public rebaseState;\\n\\n function initialize(\\n string calldata _nameArg,\\n string calldata _symbolArg,\\n address _vaultAddress\\n ) external onlyGovernor initializer {\\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\\n rebasingCreditsPerToken = 1e18;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Savings Manager contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return The total supply of OUSD.\\n */\\n function totalSupply() public view returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the _amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n if (_creditBalances[_account] == 0) return 0;\\n return\\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n public\\n view\\n returns (uint256, uint256)\\n {\\n return (_creditBalances[_account], _creditsPerToken(_account));\\n }\\n\\n /**\\n * @dev Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the _amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(\\n _value <= balanceOf(msg.sender),\\n \\\"Transfer greater than balance\\\"\\n );\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The _amount of tokens to be transferred.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) public returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n require(_value <= balanceOf(_from), \\\"Transfer greater than balance\\\");\\n\\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\\n _value\\n );\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n\\n return true;\\n }\\n\\n /**\\n * @dev Update the count of non rebasing credits in response to a transfer\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value Amount of OUSD to transfer\\n */\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\\n\\n // Credits deducted and credited might be different due to the\\n // differing creditsPerToken used by each account\\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\\n\\n _creditBalances[_from] = _creditBalances[_from].sub(\\n creditsDeducted,\\n \\\"Transfer amount exceeds balance\\\"\\n );\\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\\n\\n if (isNonRebasingTo && !isNonRebasingFrom) {\\n // Transfer to non-rebasing account from rebasing account, credits\\n // are removed from the non rebasing tally\\n nonRebasingSupply = nonRebasingSupply.add(_value);\\n // Update rebasingCredits by subtracting the deducted amount\\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\\n // Transfer to rebasing account from non-rebasing account\\n // Decreasing non-rebasing credits by the amount that was sent\\n nonRebasingSupply = nonRebasingSupply.sub(_value);\\n // Update rebasingCredits by adding the credited amount\\n rebasingCredits = rebasingCredits.add(creditsCredited);\\n }\\n }\\n\\n /**\\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n public\\n view\\n returns (uint256)\\n {\\n return _allowances[_owner][_spender];\\n }\\n\\n /**\\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\\n * msg.sender. This method is included for ERC20 compatibility.\\n * increaseAllowance and decreaseAllowance should be used instead.\\n * Changing an allowance with this method brings the risk that someone may transfer both\\n * the old and the new allowance - if they are both greater than zero - if a transfer\\n * transaction is mined before the later approve() call is mined.\\n *\\n * @param _spender The address which will spend the funds.\\n * @param _value The _amount of tokens to be spent.\\n */\\n function approve(address _spender, uint256 _value) public returns (bool) {\\n _allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\\n * This method should be used instead of approve() to avoid the double approval vulnerability\\n * described above.\\n * @param _spender The address which will spend the funds.\\n * @param _addedValue The _amount of tokens to increase the allowance by.\\n */\\n function increaseAllowance(address _spender, uint256 _addedValue)\\n public\\n returns (bool)\\n {\\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\\n .add(_addedValue);\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\\n * @param _spender The address which will spend the funds.\\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\\n */\\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\\n public\\n returns (bool)\\n {\\n uint256 oldValue = _allowances[msg.sender][_spender];\\n if (_subtractedValue >= oldValue) {\\n _allowances[msg.sender][_spender] = 0;\\n } else {\\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\\n }\\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\\n return true;\\n }\\n\\n /**\\n * @dev Mints new tokens, increasing totalSupply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n _mint(_account, _amount);\\n }\\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 * - `to` cannot be the zero address.\\n */\\n function _mint(address _account, uint256 _amount) internal nonReentrant {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\\n\\n // If the account is non rebasing and doesn't have a set creditsPerToken\\n // then set it i.e. this is a mint from a fresh contract\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.add(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.add(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.add(_amount);\\n\\n require(_totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @dev Burns tokens, decreasing totalSupply.\\n */\\n function burn(address account, uint256 amount) external onlyVault {\\n _burn(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 nonReentrant {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\\n uint256 currentCredits = _creditBalances[_account];\\n\\n // Remove the credits, burning rounding errors\\n if (\\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\\n ) {\\n // Handle dust from rounding\\n _creditBalances[_account] = 0;\\n } else if (currentCredits > creditAmount) {\\n _creditBalances[_account] = _creditBalances[_account].sub(\\n creditAmount\\n );\\n } else {\\n revert(\\\"Remove exceeds balance\\\");\\n }\\n\\n // Remove from the credit tallies and non-rebasing supply\\n if (isNonRebasingAccount) {\\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\\n } else {\\n rebasingCredits = rebasingCredits.sub(creditAmount);\\n }\\n\\n _totalSupply = _totalSupply.sub(_amount);\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n if (nonRebasingCreditsPerToken[_account] != 0) {\\n return nonRebasingCreditsPerToken[_account];\\n } else {\\n return rebasingCreditsPerToken;\\n }\\n }\\n\\n /**\\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\\n * Also, ensure contracts are non-rebasing if they have not opted in.\\n * @param _account Address of the account.\\n */\\n function _isNonRebasingAccount(address _account) internal returns (bool) {\\n bool isContract = Address.isContract(_account);\\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\\n _ensureRebasingMigration(_account);\\n }\\n return nonRebasingCreditsPerToken[_account] > 0;\\n }\\n\\n /**\\n * @dev Ensures internal account for rebasing and non-rebasing credits and\\n * supply is updated following deployment of frozen yield change.\\n */\\n function _ensureRebasingMigration(address _account) internal {\\n if (nonRebasingCreditsPerToken[_account] == 0) {\\n // Set fixed credits per token for this account\\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\\n // Update non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\\n // Update credit tallies\\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\\n }\\n }\\n\\n /**\\n * @dev Add a contract address to the non rebasing exception list. I.e. the\\n * address's balance will be part of rebases so the account will be exposed\\n * to upside and downside.\\n */\\n function rebaseOptIn() public nonReentrant {\\n require(_isNonRebasingAccount(msg.sender), \\\"Account has not opted out\\\");\\n\\n // Convert balance into the same amount at the current exchange rate\\n uint256 newCreditBalance = _creditBalances[msg.sender]\\n .mul(rebasingCreditsPerToken)\\n .div(_creditsPerToken(msg.sender));\\n\\n // Decreasing non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\\n\\n _creditBalances[msg.sender] = newCreditBalance;\\n\\n // Increase rebasing credits, totalSupply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\\n\\n rebaseState[msg.sender] = RebaseOptions.OptIn;\\n\\n // Delete any fixed credits per token\\n delete nonRebasingCreditsPerToken[msg.sender];\\n }\\n\\n /**\\n * @dev Remove a contract address to the non rebasing exception list.\\n */\\n function rebaseOptOut() public nonReentrant {\\n require(!_isNonRebasingAccount(msg.sender), \\\"Account has not opted in\\\");\\n\\n // Increase non rebasing supply\\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\\n // Set fixed credits per token\\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\\n\\n // Decrease rebasing credits, total supply remains unchanged so no\\n // adjustment necessary\\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\\n\\n // Mark explicitly opted out of rebasing\\n rebaseState[msg.sender] = RebaseOptions.OptOut;\\n }\\n\\n /**\\n * @dev Modify the supply without minting new tokens. This uses a change in\\n * the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n * @return uint256 representing the new total supply.\\n */\\n function changeSupply(uint256 _newTotalSupply)\\n external\\n onlyVault\\n nonReentrant\\n {\\n require(_totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (_totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n return;\\n }\\n\\n _totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\\n _totalSupply.sub(nonRebasingSupply)\\n );\\n\\n require(rebasingCreditsPerToken > 0, \\\"Invalid change in supply\\\");\\n\\n _totalSupply = rebasingCredits\\n .divPrecisely(rebasingCreditsPerToken)\\n .add(nonRebasingSupply);\\n\\n emit TotalSupplyUpdated(\\n _totalSupply,\\n rebasingCredits,\\n rebasingCreditsPerToken\\n );\\n }\\n}\\n\",\"keccak256\":\"0xea89a8b152b363982ba8db340b1e20c3194b2e75a06630cbbf43e3c50fff61a4\"},\"contracts/utils/Helpers.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0xd2ca92e0af883dc1aec5b22caced274e59829e0e30a9e955dcc48b8d921f5cdc\"},\"contracts/utils/InitializableERC20Detailed.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\n/**\\n * @dev Optional functions from the ERC20 standard.\\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\\n */\\ncontract InitializableERC20Detailed is IERC20 {\\n // Storage gap to skip storage from prior to OUSD reset\\n uint256[100] private _____gap;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\\n * these values are immutable: they can only be set once during\\n * construction.\\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\\n */\\n function _initialize(\\n string memory nameArg,\\n string memory symbolArg,\\n uint8 decimalsArg\\n ) internal {\\n _name = nameArg;\\n _symbol = symbolArg;\\n _decimals = decimalsArg;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view 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 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.\\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 returns (uint8) {\\n return _decimals;\\n }\\n}\\n\",\"keccak256\":\"0x7919369d0f3bd74b4f0ee78a682afe43f91b186cdd0708e303068e4feeb29007\"},\"contracts/utils/StableMath.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\n\\n// Based on StableMath from Stability Labs Pty. Ltd.\\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\\n\\nlibrary StableMath {\\n using SafeMath for uint256;\\n\\n /**\\n * @dev Scaling unit for use in specific calculations,\\n * where 1 * 10**18, or 1e18 represents a unit '1'\\n */\\n uint256 private constant FULL_SCALE = 1e18;\\n\\n /***************************************\\n Helpers\\n ****************************************/\\n\\n /**\\n * @dev Adjust the scale of an integer\\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\\n */\\n function scaleBy(uint256 x, int8 adjustment)\\n internal\\n pure\\n returns (uint256)\\n {\\n if (adjustment > 0) {\\n x = x.mul(10**uint256(adjustment));\\n } else if (adjustment < 0) {\\n x = x.div(10**uint256(adjustment * -1));\\n }\\n return x;\\n }\\n\\n /***************************************\\n Precise Arithmetic\\n ****************************************/\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\\n return mulTruncateScale(x, y, FULL_SCALE);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @param scale Scale unit\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit\\n */\\n function mulTruncateScale(\\n uint256 x,\\n uint256 y,\\n uint256 scale\\n ) internal pure returns (uint256) {\\n // e.g. assume scale = fullScale\\n // z = 10e18 * 9e17 = 9e36\\n uint256 z = x.mul(y);\\n // return 9e38 / 1e18 = 9e18\\n return z.div(scale);\\n }\\n\\n /**\\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\\n * @param x Left hand input to multiplication\\n * @param y Right hand input to multiplication\\n * @return Result after multiplying the two inputs and then dividing by the shared\\n * scale unit, rounded up to the closest base unit.\\n */\\n function mulTruncateCeil(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e17 * 17268172638 = 138145381104e17\\n uint256 scaled = x.mul(y);\\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\\n return ceil.div(FULL_SCALE);\\n }\\n\\n /**\\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\\n * @param x Left hand input to division\\n * @param y Right hand input to division\\n * @return Result after multiplying the left operand by the scale, and\\n * executing the division on the right hand input.\\n */\\n function divPrecisely(uint256 x, uint256 y)\\n internal\\n pure\\n returns (uint256)\\n {\\n // e.g. 8e18 * 1e18 = 8e36\\n uint256 z = x.mul(FULL_SCALE);\\n // e.g. 8e36 / 10e18 = 8e17\\n return z.div(y);\\n }\\n}\\n\",\"keccak256\":\"0xa77fccf850feb6d54ba3a6530f92554caef8a67a1ceb573d4f8a5d1bf64ff9d2\"},\"contracts/vault/VaultCore.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD Vault Contract\\n * @notice The Vault contract stores assets. On a deposit, OUSD will be minted\\n and sent to the depositor. On a withdrawal, OUSD will be burned and\\n assets will be sent to the withdrawer. The Vault accepts deposits of\\n interest form yield bearing strategies which will modify the supply\\n of OUSD.\\n * @author Origin Protocol Inc\\n */\\n\\nimport \\\"./VaultStorage.sol\\\";\\nimport { IOracle } from \\\"../interfaces/IOracle.sol\\\";\\nimport { IVault } from \\\"../interfaces/IVault.sol\\\";\\nimport { IBuyback } from \\\"../interfaces/IBuyback.sol\\\";\\n\\ncontract VaultCore is VaultStorage {\\n uint256 constant MAX_UINT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\\n\\n /**\\n * @dev Verifies that the rebasing is not paused.\\n */\\n modifier whenNotRebasePaused() {\\n require(!rebasePaused, \\\"Rebasing paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Verifies that the deposits are not paused.\\n */\\n modifier whenNotCapitalPaused() {\\n require(!capitalPaused, \\\"Capital paused\\\");\\n _;\\n }\\n\\n /**\\n * @dev Deposit a supported asset and mint OUSD.\\n * @param _asset Address of the asset being deposited\\n * @param _amount Amount of the asset being deposited\\n * @param _minimumOusdAmount Minimum OUSD to mint\\n */\\n function mint(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external whenNotCapitalPaused nonReentrant {\\n require(assets[_asset].isSupported, \\\"Asset is not supported\\\");\\n require(_amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n uint256 price = IOracle(priceProvider).price(_asset);\\n if (price > 1e8) {\\n price = 1e8;\\n }\\n uint256 assetDecimals = Helpers.getDecimals(_asset);\\n uint256 unitAdjustedDeposit = _amount.scaleBy(int8(18 - assetDecimals));\\n uint256 priceAdjustedDeposit = _amount.mulTruncateScale(\\n price.scaleBy(int8(10)), // 18-8 because oracles have 8 decimals precision\\n 10**assetDecimals\\n );\\n\\n if (_minimumOusdAmount > 0) {\\n require(\\n priceAdjustedDeposit >= _minimumOusdAmount,\\n \\\"Mint amount lower than minimum\\\"\\n );\\n }\\n\\n emit Mint(msg.sender, priceAdjustedDeposit);\\n\\n // Rebase must happen before any transfers occur.\\n if (unitAdjustedDeposit >= rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n\\n // Mint matching OUSD\\n oUSD.mint(msg.sender, priceAdjustedDeposit);\\n\\n // Transfer the deposited coins to the vault\\n IERC20 asset = IERC20(_asset);\\n asset.safeTransferFrom(msg.sender, address(this), _amount);\\n\\n if (unitAdjustedDeposit >= autoAllocateThreshold) {\\n _allocate();\\n }\\n }\\n\\n /**\\n * @dev Mint for multiple assets in the same call.\\n * @param _assets Addresses of assets being deposited\\n * @param _amounts Amount of each asset at the same index in the _assets\\n * to deposit.\\n * @param _minimumOusdAmount Minimum OUSD to mint\\n */\\n function mintMultiple(\\n address[] calldata _assets,\\n uint256[] calldata _amounts,\\n uint256 _minimumOusdAmount\\n ) external whenNotCapitalPaused nonReentrant {\\n require(_assets.length == _amounts.length, \\\"Parameter length mismatch\\\");\\n\\n uint256 unitAdjustedTotal = 0;\\n uint256 priceAdjustedTotal = 0;\\n uint256[] memory assetPrices = _getAssetPrices(false);\\n for (uint256 j = 0; j < _assets.length; j++) {\\n // In memoriam\\n require(assets[_assets[j]].isSupported, \\\"Asset is not supported\\\");\\n require(_amounts[j] > 0, \\\"Amount must be greater than 0\\\");\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n if (_assets[j] == allAssets[i]) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n uint256 price = assetPrices[i];\\n if (price > 1e18) {\\n price = 1e18;\\n }\\n unitAdjustedTotal = unitAdjustedTotal.add(\\n _amounts[j].scaleBy(int8(18 - assetDecimals))\\n );\\n priceAdjustedTotal = priceAdjustedTotal.add(\\n _amounts[j].mulTruncateScale(price, 10**assetDecimals)\\n );\\n }\\n }\\n }\\n\\n if (_minimumOusdAmount > 0) {\\n require(\\n priceAdjustedTotal >= _minimumOusdAmount,\\n \\\"Mint amount lower than minimum\\\"\\n );\\n }\\n\\n emit Mint(msg.sender, priceAdjustedTotal);\\n\\n // Rebase must happen before any transfers occur.\\n if (unitAdjustedTotal >= rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n\\n oUSD.mint(msg.sender, priceAdjustedTotal);\\n\\n for (uint256 i = 0; i < _assets.length; i++) {\\n IERC20 asset = IERC20(_assets[i]);\\n asset.safeTransferFrom(msg.sender, address(this), _amounts[i]);\\n }\\n\\n if (unitAdjustedTotal >= autoAllocateThreshold) {\\n _allocate();\\n }\\n }\\n\\n /**\\n * @dev Withdraw a supported asset and burn OUSD.\\n * @param _amount Amount of OUSD to burn\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount)\\n public\\n whenNotCapitalPaused\\n nonReentrant\\n {\\n if (_amount > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n _redeem(_amount, _minimumUnitAmount);\\n }\\n\\n /**\\n * @dev Withdraw a supported asset and burn OUSD.\\n * @param _amount Amount of OUSD to burn\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function _redeem(uint256 _amount, uint256 _minimumUnitAmount) internal {\\n require(_amount > 0, \\\"Amount must be greater than 0\\\");\\n\\n uint256 _totalSupply = oUSD.totalSupply();\\n uint256 _backingValue = _totalValue();\\n\\n if (maxSupplyDiff > 0) {\\n // Allow a max difference of maxSupplyDiff% between\\n // backing assets value and OUSD total supply\\n uint256 diff = _totalSupply.divPrecisely(_backingValue);\\n\\n require(\\n (diff > 1e18 ? diff.sub(1e18) : uint256(1e18).sub(diff)) <=\\n maxSupplyDiff,\\n \\\"Backing supply liquidity error\\\"\\n );\\n }\\n\\n emit Redeem(msg.sender, _amount);\\n\\n // Calculate redemption outputs\\n uint256[] memory outputs = _calculateRedeemOutputs(_amount);\\n // Send outputs\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n if (outputs[i] == 0) continue;\\n\\n IERC20 asset = IERC20(allAssets[i]);\\n\\n if (asset.balanceOf(address(this)) >= outputs[i]) {\\n // Use Vault funds first if sufficient\\n asset.safeTransfer(msg.sender, outputs[i]);\\n } else {\\n address strategyAddr = assetDefaultStrategies[allAssets[i]];\\n if (strategyAddr != address(0)) {\\n // Nothing in Vault, but something in Strategy, send from there\\n IStrategy strategy = IStrategy(strategyAddr);\\n strategy.withdraw(msg.sender, allAssets[i], outputs[i]);\\n } else {\\n // Cant find funds anywhere\\n revert(\\\"Liquidity error\\\");\\n }\\n }\\n }\\n\\n if (_minimumUnitAmount > 0) {\\n uint256 unitTotal = 0;\\n for (uint256 i = 0; i < outputs.length; i++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n unitTotal = unitTotal.add(\\n outputs[i].scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n require(\\n unitTotal >= _minimumUnitAmount,\\n \\\"Redeem amount lower than minimum\\\"\\n );\\n }\\n\\n oUSD.burn(msg.sender, _amount);\\n\\n // Until we can prove that we won't affect the prices of our assets\\n // by withdrawing them, this should be here.\\n // It's possible that a strategy was off on its asset total, perhaps\\n // a reward token sold for more or for less than anticipated.\\n if (_amount > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n }\\n\\n /**\\n * @notice Withdraw a supported asset and burn all OUSD.\\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\\n */\\n function redeemAll(uint256 _minimumUnitAmount)\\n external\\n whenNotCapitalPaused\\n nonReentrant\\n {\\n // Unfortunately we have to do balanceOf twice, the rebase may change\\n // the account balance\\n if (oUSD.balanceOf(msg.sender) > rebaseThreshold && !rebasePaused) {\\n _rebase();\\n }\\n _redeem(oUSD.balanceOf(msg.sender), _minimumUnitAmount);\\n }\\n\\n /**\\n * @notice Allocate unallocated funds on Vault to strategies.\\n * @dev Allocate unallocated funds on Vault to strategies.\\n **/\\n function allocate() public whenNotCapitalPaused nonReentrant {\\n _allocate();\\n }\\n\\n /**\\n * @notice Allocate unallocated funds on Vault to strategies.\\n * @dev Allocate unallocated funds on Vault to strategies.\\n **/\\n function _allocate() internal {\\n uint256 vaultValue = _totalValueInVault();\\n // Nothing in vault to allocate\\n if (vaultValue == 0) return;\\n uint256 strategiesValue = _totalValueInStrategies();\\n // We have a method that does the same as this, gas optimisation\\n uint256 calculatedTotalValue = vaultValue.add(strategiesValue);\\n\\n // We want to maintain a buffer on the Vault so calculate a percentage\\n // modifier to multiply each amount being allocated by to enforce the\\n // vault buffer\\n uint256 vaultBufferModifier;\\n if (strategiesValue == 0) {\\n // Nothing in Strategies, allocate 100% minus the vault buffer to\\n // strategies\\n vaultBufferModifier = uint256(1e18).sub(vaultBuffer);\\n } else {\\n vaultBufferModifier = vaultBuffer.mul(calculatedTotalValue).div(\\n vaultValue\\n );\\n if (1e18 > vaultBufferModifier) {\\n // E.g. 1e18 - (1e17 * 10e18)/5e18 = 8e17\\n // (5e18 * 8e17) / 1e18 = 4e18 allocated from Vault\\n vaultBufferModifier = uint256(1e18).sub(vaultBufferModifier);\\n } else {\\n // We need to let the buffer fill\\n return;\\n }\\n }\\n if (vaultBufferModifier == 0) return;\\n\\n // Iterate over all assets in the Vault and allocate the the appropriate\\n // strategy\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n IERC20 asset = IERC20(allAssets[i]);\\n uint256 assetBalance = asset.balanceOf(address(this));\\n // No balance, nothing to do here\\n if (assetBalance == 0) continue;\\n\\n // Multiply the balance by the vault buffer modifier and truncate\\n // to the scale of the asset decimals\\n uint256 allocateAmount = assetBalance.mulTruncate(\\n vaultBufferModifier\\n );\\n\\n address depositStrategyAddr = assetDefaultStrategies[address(\\n asset\\n )];\\n\\n if (depositStrategyAddr != address(0) && allocateAmount > 0) {\\n IStrategy strategy = IStrategy(depositStrategyAddr);\\n // Transfer asset to Strategy and call deposit method to\\n // mint or take required action\\n asset.safeTransfer(address(strategy), allocateAmount);\\n strategy.deposit(address(asset), allocateAmount);\\n }\\n }\\n\\n // Harvest for all reward tokens above reward liquidation threshold\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n address rewardTokenAddress = strategy.rewardTokenAddress();\\n if (rewardTokenAddress != address(0)) {\\n uint256 liquidationThreshold = strategy\\n .rewardLiquidationThreshold();\\n if (liquidationThreshold == 0) {\\n // No threshold set, always harvest from strategy\\n IVault(address(this)).harvest(allStrategies[i]);\\n } else {\\n // Check balance against liquidation threshold\\n // Note some strategies don't hold the reward token balance\\n // on their contract so the liquidation threshold should be\\n // set to 0\\n IERC20 rewardToken = IERC20(rewardTokenAddress);\\n uint256 rewardTokenAmount = rewardToken.balanceOf(\\n allStrategies[i]\\n );\\n if (rewardTokenAmount >= liquidationThreshold) {\\n IVault(address(this)).harvest(allStrategies[i]);\\n }\\n }\\n }\\n }\\n\\n // Trigger OGN Buyback\\n IBuyback(trusteeAddress).swap();\\n }\\n\\n /**\\n * @dev Calculate the total value of assets held by the Vault and all\\n * strategies and update the supply of OUSD.\\n */\\n function rebase() public whenNotRebasePaused nonReentrant {\\n _rebase();\\n }\\n\\n /**\\n * @dev Calculate the total value of assets held by the Vault and all\\n * strategies and update the supply of OUSD, optionaly sending a\\n * portion of the yield to the trustee.\\n */\\n function _rebase() internal whenNotRebasePaused {\\n uint256 ousdSupply = oUSD.totalSupply();\\n if (ousdSupply == 0) {\\n return;\\n }\\n uint256 vaultValue = _totalValue();\\n\\n // Yield fee collection\\n address _trusteeAddress = trusteeAddress; // gas savings\\n if (_trusteeAddress != address(0) && (vaultValue > ousdSupply)) {\\n uint256 yield = vaultValue.sub(ousdSupply);\\n uint256 fee = yield.mul(trusteeFeeBps).div(10000);\\n require(yield > fee, \\\"Fee must not be greater than yield\\\");\\n if (fee > 0) {\\n oUSD.mint(_trusteeAddress, fee);\\n }\\n emit YieldDistribution(_trusteeAddress, yield, fee);\\n }\\n\\n // Only rachet OUSD supply upwards\\n ousdSupply = oUSD.totalSupply(); // Final check should use latest value\\n if (vaultValue > ousdSupply) {\\n oUSD.changeSupply(vaultValue);\\n }\\n }\\n\\n /**\\n * @dev Determine the total value of assets held by the vault and its\\n * strategies.\\n * @return uint256 value Total value in USD (1e18)\\n */\\n function totalValue() external view returns (uint256 value) {\\n value = _totalValue();\\n }\\n\\n /**\\n * @dev Internal Calculate the total value of the assets held by the\\n * vault and its strategies.\\n * @return uint256 value Total value in USD (1e18)\\n */\\n function _totalValue() internal view returns (uint256 value) {\\n return _totalValueInVault().add(_totalValueInStrategies());\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held in Vault.\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInVault() internal view returns (uint256 value) {\\n for (uint256 y = 0; y < allAssets.length; y++) {\\n IERC20 asset = IERC20(allAssets[y]);\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\\n uint256 balance = asset.balanceOf(address(this));\\n if (balance > 0) {\\n value = value.add(balance.scaleBy(int8(18 - assetDecimals)));\\n }\\n }\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held in Strategies.\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInStrategies() internal view returns (uint256 value) {\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n value = value.add(_totalValueInStrategy(allStrategies[i]));\\n }\\n }\\n\\n /**\\n * @dev Internal to calculate total value of all assets held by strategy.\\n * @param _strategyAddr Address of the strategy\\n * @return uint256 Total value in ETH (1e18)\\n */\\n function _totalValueInStrategy(address _strategyAddr)\\n internal\\n view\\n returns (uint256 value)\\n {\\n IStrategy strategy = IStrategy(_strategyAddr);\\n for (uint256 y = 0; y < allAssets.length; y++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\\n if (strategy.supportsAsset(allAssets[y])) {\\n uint256 balance = strategy.checkBalance(allAssets[y]);\\n if (balance > 0) {\\n value = value.add(\\n balance.scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Get the balance of an asset held in Vault and all strategies.\\n * @param _asset Address of asset\\n * @return uint256 Balance of asset in decimals of asset\\n */\\n function checkBalance(address _asset) external view returns (uint256) {\\n return _checkBalance(_asset);\\n }\\n\\n /**\\n * @notice Get the balance of an asset held in Vault and all strategies.\\n * @param _asset Address of asset\\n * @return uint256 Balance of asset in decimals of asset\\n */\\n function _checkBalance(address _asset)\\n internal\\n view\\n returns (uint256 balance)\\n {\\n IERC20 asset = IERC20(_asset);\\n balance = asset.balanceOf(address(this));\\n for (uint256 i = 0; i < allStrategies.length; i++) {\\n IStrategy strategy = IStrategy(allStrategies[i]);\\n if (strategy.supportsAsset(_asset)) {\\n balance = balance.add(strategy.checkBalance(_asset));\\n }\\n }\\n }\\n\\n /**\\n * @notice Get the balance of all assets held in Vault and all strategies.\\n * @return uint256 Balance of all assets (1e18)\\n */\\n function _checkBalance() internal view returns (uint256 balance) {\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\\n balance = balance.add(\\n _checkBalance(allAssets[i]).scaleBy(int8(18 - assetDecimals))\\n );\\n }\\n }\\n\\n /**\\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\\n * coins that will be returned\\n */\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory)\\n {\\n return _calculateRedeemOutputs(_amount);\\n }\\n\\n /**\\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\\n * coins that will be returned.\\n * @return Array of amounts respective to the supported assets\\n */\\n function _calculateRedeemOutputs(uint256 _amount)\\n internal\\n view\\n returns (uint256[] memory outputs)\\n {\\n // We always give out coins in proportion to how many we have,\\n // Now if all coins were the same value, this math would easy,\\n // just take the percentage of each coin, and multiply by the\\n // value to be given out. But if coins are worth more than $1,\\n // then we would end up handing out too many coins. We need to\\n // adjust by the total value of coins.\\n //\\n // To do this, we total up the value of our coins, by their\\n // percentages. Then divide what we would otherwise give out by\\n // this number.\\n //\\n // Let say we have 100 DAI at $1.06 and 200 USDT at $1.00.\\n // So for every 1 DAI we give out, we'll be handing out 2 USDT\\n // Our total output ratio is: 33% * 1.06 + 66% * 1.00 = 1.02\\n //\\n // So when calculating the output, we take the percentage of\\n // each coin, times the desired output value, divided by the\\n // totalOutputRatio.\\n //\\n // For example, withdrawing: 30 OUSD:\\n // DAI 33% * 30 / 1.02 = 9.80 DAI\\n // USDT = 66 % * 30 / 1.02 = 19.60 USDT\\n //\\n // Checking these numbers:\\n // 9.80 DAI * 1.06 = $10.40\\n // 19.60 USDT * 1.00 = $19.60\\n //\\n // And so the user gets $10.40 + $19.60 = $30 worth of value.\\n\\n uint256 assetCount = getAssetCount();\\n uint256[] memory assetPrices = _getAssetPrices(true);\\n uint256[] memory assetBalances = new uint256[](assetCount);\\n uint256[] memory assetDecimals = new uint256[](assetCount);\\n uint256 totalBalance = 0;\\n uint256 totalOutputRatio = 0;\\n outputs = new uint256[](assetCount);\\n\\n // Calculate redeem fee\\n if (redeemFeeBps > 0) {\\n uint256 redeemFee = _amount.mul(redeemFeeBps).div(10000);\\n _amount = _amount.sub(redeemFee);\\n }\\n\\n // Calculate assets balances and decimals once,\\n // for a large gas savings.\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 balance = _checkBalance(allAssets[i]);\\n uint256 decimals = Helpers.getDecimals(allAssets[i]);\\n assetBalances[i] = balance;\\n assetDecimals[i] = decimals;\\n totalBalance = totalBalance.add(\\n balance.scaleBy(int8(18 - decimals))\\n );\\n }\\n // Calculate totalOutputRatio\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n uint256 price = assetPrices[i];\\n // Never give out more than one\\n // stablecoin per dollar of OUSD\\n if (price < 1e18) {\\n price = 1e18;\\n }\\n uint256 ratio = assetBalances[i]\\n .scaleBy(int8(18 - assetDecimals[i]))\\n .mul(price)\\n .div(totalBalance);\\n totalOutputRatio = totalOutputRatio.add(ratio);\\n }\\n // Calculate final outputs\\n uint256 factor = _amount.divPrecisely(totalOutputRatio);\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n outputs[i] = assetBalances[i].mul(factor).div(totalBalance);\\n }\\n }\\n\\n /**\\n * @notice Get an array of the supported asset prices in USD.\\n * @return uint256[] Array of asset prices in USD (1e18)\\n */\\n function _getAssetPrices(bool useMax)\\n internal\\n view\\n returns (uint256[] memory assetPrices)\\n {\\n assetPrices = new uint256[](getAssetCount());\\n\\n IOracle oracle = IOracle(priceProvider);\\n // Price from Oracle is returned with 8 decimals\\n // _amount is in assetDecimals\\n for (uint256 i = 0; i < allAssets.length; i++) {\\n assetPrices[i] = oracle.price(allAssets[i]).scaleBy(int8(18 - 8));\\n }\\n }\\n\\n /***************************************\\n Utils\\n ****************************************/\\n\\n /**\\n * @dev Return the number of assets suppported by the Vault.\\n */\\n function getAssetCount() public view returns (uint256) {\\n return allAssets.length;\\n }\\n\\n /**\\n * @dev Return all asset addresses in order\\n */\\n function getAllAssets() external view returns (address[] memory) {\\n return allAssets;\\n }\\n\\n /**\\n * @dev Return the number of strategies active on the Vault.\\n */\\n function getStrategyCount() external view returns (uint256) {\\n return allStrategies.length;\\n }\\n\\n function isSupportedAsset(address _asset) external view returns (bool) {\\n return assets[_asset].isSupported;\\n }\\n\\n /**\\n * @dev Falldown to the admin implementation\\n * @notice This is a catch all for all functions not declared in core\\n */\\n function() external payable {\\n bytes32 slot = adminImplPosition;\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize)\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas, sload(slot), 0, calldatasize, 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize)\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize)\\n }\\n default {\\n return(0, returndatasize)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7dff24efb502d476c147d671bb4080a596fe020dbf9f7b2643fc4eb2f1061717\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"pragma solidity 0.5.11;\\n\\n/**\\n * @title OUSD VaultStorage Contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport { SafeMath } from \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport {\\n Initializable\\n} from \\\"@openzeppelin/upgrades/contracts/Initializable.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\nimport { StableMath } from \\\"../utils/StableMath.sol\\\";\\n\\ncontract VaultStorage is Initializable, Governable {\\n using SafeMath for uint256;\\n using StableMath for uint256;\\n using SafeMath for int256;\\n using SafeERC20 for IERC20;\\n\\n event AssetSupported(address _asset);\\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\\n event PriceProviderUpdated(address _priceProvider);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event UniswapUpdated(address _address);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n\\n // Assets supported by the Vault, i.e. Stablecoins\\n struct Asset {\\n bool isSupported;\\n }\\n mapping(address => Asset) assets;\\n address[] allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n mapping(address => Strategy) strategies;\\n address[] allStrategies;\\n\\n // Address of the Oracle price provider contract\\n address public priceProvider;\\n // Pausing bools\\n bool public rebasePaused = false;\\n bool public capitalPaused = true;\\n // Redemption fee in basis points\\n uint256 public redeemFeeBps;\\n // Buffer of assets to keep in Vault to handle (most) withdrawals\\n uint256 public vaultBuffer;\\n // Mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n // Mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n OUSD oUSD;\\n\\n //keccak256(\\\"OUSD.vault.governor.admin.impl\\\");\\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\\n\\n // Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n // Address of Uniswap\\n address public uniswapAddr = address(0);\\n\\n // Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n // Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n mapping(address => address) public assetDefaultStrategies;\\n\\n uint256 public maxSupplyDiff;\\n\\n // Trustee contract that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n // Amount of yield collected in basis points\\n uint256 public trusteeFeeBps;\\n\\n /**\\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\\n * @param newImpl address of the implementation\\n */\\n function setAdminImpl(address newImpl) external onlyGovernor {\\n require(\\n Address.isContract(newImpl),\\n \\\"new implementation is not a contract\\\"\\n );\\n bytes32 position = adminImplPosition;\\n assembly {\\n sstore(position, newImpl)\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc945fa95b0fb31ae523cf91bd89bbf1289de38b02a8b082b98fed152c00c7746\"}},\"version\":1}", + "bytecode": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b600080516020620037d383398151915255565b600080516020620037d38339815191525490565b6136e180620000f26000396000f3fe6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610ad1565b3480156102ed57600080fd5b50610233610ad7565b34801561030257600080fd5b5061030b610add565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610b3f565b34801561037c57600080fd5b5061025a610b45565b34801561039157600080fd5b50610233610b54565b3480156103a657600080fd5b506103af610b5a565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610b6a565b3480156103e457600080fd5b506102ca610b79565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610bdb565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610bec565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610bf7565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610dc7565b3480156104b057600080fd5b50610233610eae565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610eb4565b3480156104f857600080fd5b50610233610ed2565b34801561050d57600080fd5b50610233610ed8565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610ede565b34801561055557600080fd5b506102ca610ef9565b34801561056a57600080fd5b506102ca610fb4565b34801561057f57600080fd5b5061025a611069565b34801561059457600080fd5b506103af611078565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b031661109b565b3480156105dc57600080fd5b50610233611147565b3480156105f157600080fd5b506103af611151565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b919350915035611161565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b031661165c565b60385481565b600061070c61171d565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a3833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603754604080516315d5220f60e31b81526001600160a01b0388811660048301529151600093929092169163aea9107891602480820192602092909190829003018186803b1580156108d857600080fd5b505afa1580156108ec573d6000803e3d6000fd5b505050506040513d602081101561090257600080fd5b505190506305f5e10081111561091957506305f5e1005b600061092487611742565b9050600061093c87601284900363ffffffff6117fc16565b9050600061096661095485600a63ffffffff6117fc16565b8990600a86900a63ffffffff61185616565b905086156109c357868110156109c3576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a1a5750603754600160a01b900460ff16155b15610a2757610a27611884565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b508b9250610ab09150506001600160a01b03821633308c63ffffffff611bab16565b603a548310610ac157610ac1611c0b565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b3557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b17575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610b81612196565b6001600160a01b0316336001600160a01b031614610bd05760405162461bcd60e51b815260040180806020018281038252603081526020018061367d6030913960400191505060405180910390fd5b610bd9336121bb565b565b6000610be682612269565b92915050565b6060610be68261242a565b603754600160a81b900460ff1615610c47576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610c9f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b54603c54604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610cf157600080fd5b505afa158015610d05573d6000803e3d6000fd5b505050506040513d6020811015610d1b57600080fd5b5051118015610d345750603754600160a01b900460ff16155b15610d4157610d41611884565b603c54604080516370a0823160e01b81523360048201529051610dbf926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610d8d57600080fd5b505afa158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b5051846126eb565b506001905550565b603754600160a81b900460ff1615610e17576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610e6f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b5484118015610e8e5750603754600160a01b900460ff16155b15610e9b57610e9b611884565b610ea584846126eb565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610f49576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610fa1576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610fad611c0b565b5060019055565b603754600160a01b900460ff1615611005576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206135a38339815191528054600281141561105d576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610fad611884565b6037546001600160a01b031681565b600061108261171d565b6001600160a01b0316336001600160a01b031614905090565b6110a3611078565b6110f4576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6110fd81612c9c565b806001600160a01b031661110f61171d565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612cc0565b603754600160a81b900460ff1681565b603754600160a81b900460ff16156111b1576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415611209576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255858414611261576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b600080606061126f82612ce1565b905060005b898110156114a857603360008c8c8481811061128c57fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166112fc576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061130a57fe5b9050602002013511611363576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b60345481101561149f576034818154811061137d57fe5b6000918252602090912001546001600160a01b03168c8c8481811061139e57fe5b905060200201356001600160a01b03166001600160a01b031614156114975760006113e9603483815481106113cf57fe5b6000918252602090912001546001600160a01b0316611742565b905060008483815181106113f957fe5b60200260200101519050670de0b6b3a764000081111561141e5750670de0b6b3a76400005b611456611449836012038e8e8881811061143457fe5b905060200201356117fc90919063ffffffff16565b889063ffffffff612df716565b96506114926114858284600a0a8f8f8981811061146f57fe5b905060200201356118569092919063ffffffff16565b879063ffffffff612df716565b955050505b600101611366565b50600101611274565b5085156115045785821015611504576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b54831015801561155b5750603754600160a01b900460ff16155b1561156857611568611884565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b1580156115bb57600080fd5b505af11580156115cf573d6000803e3d6000fd5b506000925050505b8981101561163a5760008b8b838181106115ed57fe5b905060200201356001600160a01b0316905061163133308c8c8681811061161057fe5b90506020020135846001600160a01b0316611bab909392919063ffffffff16565b506001016115d7565b50603a54831061164c5761164c611c0b565b5050506001825550505050505050565b611664611078565b6116b5576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6116be81612e58565b6116f95760405162461bcd60e51b81526004018080602001828103825260248152602001806135c36024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561177e57600080fd5b505afa158015611792573d6000803e3d6000fd5b505050506040513d60208110156117a857600080fd5b505160ff169050600481108015906117c1575060128111155b610be65760405162461bcd60e51b81526004018080602001828103825260298152602001806135e76029913960400191505060405180910390fd5b6000808260000b13156118275761182083600084900b600a0a63ffffffff612e9416565b925061184f565b60008260000b121561184f5761184c836000848103900b600a0a63ffffffff612eed16565b92505b5090919050565b600080611869858563ffffffff612e9416565b905061187b818463ffffffff612eed16565b95945050505050565b603754600160a01b900460ff16156118d5576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561191a57600080fd5b505afa15801561192e573d6000803e3d6000fd5b505050506040513d602081101561194457600080fd5b50519050806119535750610bd9565b600061195d612cc0565b6042549091506001600160a01b0316801580159061197a57508282115b15611abc576000611991838563ffffffff612f2f16565b905060006119bc6127106119b060435485612e9490919063ffffffff16565b9063ffffffff612eed16565b90508082116119fc5760405162461bcd60e51b81526004018080602001828103825260228152602001806136316022913960400191505060405180910390fd5b8015611a7057603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611a5757600080fd5b505af1158015611a6b573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0a57600080fd5b505afa158015611b1e573d6000803e3d6000fd5b505050506040513d6020811015611b3457600080fd5b5051925082821115611ba657603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611b8d57600080fd5b505af1158015611ba1573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611c05908590612f71565b50505050565b6000611c15613129565b905080611c225750610bd9565b6000611c2c613219565b90506000611c40838363ffffffff612df716565b9050600082611c6c57603954611c6590670de0b6b3a76400009063ffffffff612f2f16565b9050611cb8565b611c85846119b084603954612e9490919063ffffffff16565b905080670de0b6b3a76400001115611caf57611c65670de0b6b3a76400008263ffffffff612f2f16565b50505050610bd9565b80611cc65750505050610bd9565b60005b603454811015611e5557600060348281548110611ce257fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611d3557600080fd5b505afa158015611d49573d6000803e3d6000fd5b505050506040513d6020811015611d5f57600080fd5b5051905080611d6f575050611e4d565b6000611d81828663ffffffff61326b16565b6001600160a01b03808516600090815260406020819052902054919250168015801590611dae5750600082115b15611e485780611dce6001600160a01b038616828563ffffffff61328016565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611e2e57600080fd5b505af1158015611e42573d6000803e3d6000fd5b50505050505b505050505b600101611cc9565b5060005b60365481101561212757600060368281548110611e7257fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b158015611ebf57600080fd5b505afa158015611ed3573d6000803e3d6000fd5b505050506040513d6020811015611ee957600080fd5b505190506001600160a01b0381161561211d576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b5051905080611ff057306001600160a01b0316630e5c011e60368681548110611f8657fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b5050505061211b565b60008290506000816001600160a01b03166370a082316036888154811061201357fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561206157600080fd5b505afa158015612075573d6000803e3d6000fd5b505050506040513d602081101561208b57600080fd5b5051905082811061211857306001600160a01b0316630e5c011e603688815481106120b257fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b1580156120ff57600080fd5b505af1158015612113573d6000803e3d6000fd5b505050505b50505b505b5050600101611e59565b50604260009054906101000a90046001600160a01b03166001600160a01b0316638119c0656040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561217857600080fd5b505af115801561218c573d6000803e3d6000fd5b5050505050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116612216576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661222861171d565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3612266816132d2565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156122b457600080fd5b505afa1580156122c8573d6000803e3d6000fd5b505050506040513d60208110156122de57600080fd5b5051915060005b603654811015612423576000603682815481106122fe57fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561235457600080fd5b505afa158015612368573d6000803e3d6000fd5b505050506040513d602081101561237e57600080fd5b50511561241a57612417816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156123de57600080fd5b505afa1580156123f2573d6000803e3d6000fd5b505050506040513d602081101561240857600080fd5b5051859063ffffffff612df716565b93505b506001016122e5565b5050919050565b60606000612436610ed8565b905060606124446001612ce1565b9050606082604051908082528060200260200182016040528015612472578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156124a1578160200160208202803883390190505b5060408051868152602080880282010190915290915060009081908680156124d3578160200160208202803883390190505b50603854909750156125125760006124fc6127106119b06038548c612e9490919063ffffffff16565b905061250e898263ffffffff612f2f16565b9850505b60005b6034548110156125c257600061254b6034838154811061253157fe5b6000918252602090912001546001600160a01b0316612269565b9050600061255f603484815481106113cf57fe5b90508187848151811061256e57fe5b6020026020010181815250508086848151811061258757fe5b60209081029190910101526125b66125a983601284900363ffffffff6117fc16565b869063ffffffff612df716565b94505050600101612515565b5060005b6034548110156126735760008682815181106125de57fe5b60200260200101519050670de0b6b3a76400008110156126035750670de0b6b3a76400005b6000612655856119b0846126498a888151811061261c57fe5b60200260200101516012038c898151811061263357fe5b60200260200101516117fc90919063ffffffff16565b9063ffffffff612e9416565b9050612667848263ffffffff612df716565b935050506001016125c6565b506000612686898363ffffffff6132f616565b905060005b6034548110156126de576126bf846119b0848985815181106126a957fe5b6020026020010151612e9490919063ffffffff16565b8982815181106126cb57fe5b602090810291909101015260010161268b565b5050505050505050919050565b60008211612740576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561278557600080fd5b505afa158015612799573d6000803e3d6000fd5b505050506040513d60208110156127af57600080fd5b5051905060006127bd612cc0565b604154909150156128785760006127da838363ffffffff6132f616565b9050604154670de0b6b3a7640000821161280b57612806670de0b6b3a76400008363ffffffff612f2f16565b612823565b61282382670de0b6b3a764000063ffffffff612f2f16565b1115612876576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810186905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160606128be8561242a565b905060005b603454811015612b54578181815181106128d957fe5b6020026020010151600014156128ee57612b4c565b6000603482815481106128fd57fe5b60009182526020909120015483516001600160a01b03909116915083908390811061292457fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b5051106129e9576129e4338484815181106129c357fe5b6020026020010151836001600160a01b03166132809092919063ffffffff16565b612b4a565b600060406000603485815481106129fc57fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612b09576000819050806001600160a01b031663d9caed123360348781548110612a5157fe5b9060005260206000200160009054906101000a90046001600160a01b0316888881518110612a7b57fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612aeb57600080fd5b505af1158015612aff573d6000803e3d6000fd5b5050505050612b48565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b6001016128c3565b508315612c02576000805b8251811015612baa576000612b7a603483815481106113cf57fe5b9050612b9f612b928260120386858151811061263357fe5b849063ffffffff612df716565b925050600101612b5f565b5084811015612c00576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612c5557600080fd5b505af1158015612c69573d6000803e3d6000fd5b50505050603b5485118015612c885750603754600160a01b900460ff16155b15612c9557612c95611884565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612ccd613219565b612cd5613129565b9063ffffffff612df716565b6060612ceb610ed8565b604051908082528060200260200182016040528015612d14578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561242357612dd8600a836001600160a01b031663aea9107860348581548110612d5257fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015612da057600080fd5b505afa158015612db4573d6000803e3d6000fd5b505050506040513d6020811015612dca57600080fd5b50519063ffffffff6117fc16565b838281518110612de457fe5b6020908102919091010152600101612d27565b600082820183811015612e51576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612e8c57508115155b949350505050565b600082612ea357506000610be6565b82820282848281612eb057fe5b0414612e515760405162461bcd60e51b81526004018080602001828103825260218152602001806136106021913960400191505060405180910390fd5b6000612e5183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613323565b6000612e5183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506133c5565b612f83826001600160a01b0316612e58565b612fd4576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106130125780518252601f199092019160209182019101612ff3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613074576040519150601f19603f3d011682016040523d82523d6000602084013e613079565b606091505b5091509150816130d0576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611c05578080602001905160208110156130ec57600080fd5b5051611c055760405162461bcd60e51b815260040180806020018281038252602a815260200180613653602a913960400191505060405180910390fd5b6000805b6034548110156132155760006034828154811061314657fe5b6000918252602082200154603480546001600160a01b03909216935061317091859081106113cf57fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156131bc57600080fd5b505afa1580156131d0573d6000803e3d6000fd5b505050506040513d60208110156131e657600080fd5b50519050801561320a576132076125a982601285900363ffffffff6117fc16565b94505b50505060010161312d565b5090565b6000805b603654811015613215576132616132546036838154811061323a57fe5b6000918252602090912001546001600160a01b031661341f565b839063ffffffff612df716565b915060010161321d565b6000612e518383670de0b6b3a7640000611856565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611ba6908490612f71565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061331184670de0b6b3a764000063ffffffff612e9416565b9050612e8c818463ffffffff612eed16565b600081836133af5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561337457818101518382015260200161335c565b50505050905090810190601f1680156133a15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816133bb57fe5b0495945050505050565b600081848411156134175760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561337457818101518382015260200161335c565b505050900390565b600081815b603454811015612423576000613440603483815481106113cf57fe5b9050826001600160a01b031663aa388af66034848154811061345e57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156134ac57600080fd5b505afa1580156134c0573d6000803e3d6000fd5b505050506040513d60208110156134d657600080fd5b505115613599576000836001600160a01b0316635f515226603485815481106134fb57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561354957600080fd5b505afa15801561355d573d6000803e3d6000fd5b505050506040513d602081101561357357600080fd5b505190508015613597576135946125a982601285900363ffffffff6117fc16565b94505b505b5060010161342456fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820f5ce484058ce120d7bb6fefde3051498b9396da8f85e58bb4fb70cd2ed9251b264736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610ad1565b3480156102ed57600080fd5b50610233610ad7565b34801561030257600080fd5b5061030b610add565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610b3f565b34801561037c57600080fd5b5061025a610b45565b34801561039157600080fd5b50610233610b54565b3480156103a657600080fd5b506103af610b5a565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610b6a565b3480156103e457600080fd5b506102ca610b79565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610bdb565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610bec565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610bf7565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610dc7565b3480156104b057600080fd5b50610233610eae565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610eb4565b3480156104f857600080fd5b50610233610ed2565b34801561050d57600080fd5b50610233610ed8565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610ede565b34801561055557600080fd5b506102ca610ef9565b34801561056a57600080fd5b506102ca610fb4565b34801561057f57600080fd5b5061025a611069565b34801561059457600080fd5b506103af611078565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b031661109b565b3480156105dc57600080fd5b50610233611147565b3480156105f157600080fd5b506103af611151565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b919350915035611161565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b031661165c565b60385481565b600061070c61171d565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a3833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603754604080516315d5220f60e31b81526001600160a01b0388811660048301529151600093929092169163aea9107891602480820192602092909190829003018186803b1580156108d857600080fd5b505afa1580156108ec573d6000803e3d6000fd5b505050506040513d602081101561090257600080fd5b505190506305f5e10081111561091957506305f5e1005b600061092487611742565b9050600061093c87601284900363ffffffff6117fc16565b9050600061096661095485600a63ffffffff6117fc16565b8990600a86900a63ffffffff61185616565b905086156109c357868110156109c3576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a1a5750603754600160a01b900460ff16155b15610a2757610a27611884565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b508b9250610ab09150506001600160a01b03821633308c63ffffffff611bab16565b603a548310610ac157610ac1611c0b565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b3557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b17575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610b81612196565b6001600160a01b0316336001600160a01b031614610bd05760405162461bcd60e51b815260040180806020018281038252603081526020018061367d6030913960400191505060405180910390fd5b610bd9336121bb565b565b6000610be682612269565b92915050565b6060610be68261242a565b603754600160a81b900460ff1615610c47576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610c9f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b54603c54604080516370a0823160e01b815233600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015610cf157600080fd5b505afa158015610d05573d6000803e3d6000fd5b505050506040513d6020811015610d1b57600080fd5b5051118015610d345750603754600160a01b900460ff16155b15610d4157610d41611884565b603c54604080516370a0823160e01b81523360048201529051610dbf926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610d8d57600080fd5b505afa158015610da1573d6000803e3d6000fd5b505050506040513d6020811015610db757600080fd5b5051846126eb565b506001905550565b603754600160a81b900460ff1615610e17576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610e6f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603b5484118015610e8e5750603754600160a01b900460ff16155b15610e9b57610e9b611884565b610ea584846126eb565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610f49576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415610fa1576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610fad611c0b565b5060019055565b603754600160a01b900460ff1615611005576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206135a38339815191528054600281141561105d576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610fad611884565b6037546001600160a01b031681565b600061108261171d565b6001600160a01b0316336001600160a01b031614905090565b6110a3611078565b6110f4576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6110fd81612c9c565b806001600160a01b031661110f61171d565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612cc0565b603754600160a81b900460ff1681565b603754600160a81b900460ff16156111b1576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206135a383398151915280546002811415611209576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255858414611261576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b600080606061126f82612ce1565b905060005b898110156114a857603360008c8c8481811061128c57fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff166112fc576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061130a57fe5b9050602002013511611363576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b60345481101561149f576034818154811061137d57fe5b6000918252602090912001546001600160a01b03168c8c8481811061139e57fe5b905060200201356001600160a01b03166001600160a01b031614156114975760006113e9603483815481106113cf57fe5b6000918252602090912001546001600160a01b0316611742565b905060008483815181106113f957fe5b60200260200101519050670de0b6b3a764000081111561141e5750670de0b6b3a76400005b611456611449836012038e8e8881811061143457fe5b905060200201356117fc90919063ffffffff16565b889063ffffffff612df716565b96506114926114858284600a0a8f8f8981811061146f57fe5b905060200201356118569092919063ffffffff16565b879063ffffffff612df716565b955050505b600101611366565b50600101611274565b5085156115045785821015611504576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b54831015801561155b5750603754600160a01b900460ff16155b1561156857611568611884565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b1580156115bb57600080fd5b505af11580156115cf573d6000803e3d6000fd5b506000925050505b8981101561163a5760008b8b838181106115ed57fe5b905060200201356001600160a01b0316905061163133308c8c8681811061161057fe5b90506020020135846001600160a01b0316611bab909392919063ffffffff16565b506001016115d7565b50603a54831061164c5761164c611c0b565b5050506001825550505050505050565b611664611078565b6116b5576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b6116be81612e58565b6116f95760405162461bcd60e51b81526004018080602001828103825260248152602001806135c36024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561177e57600080fd5b505afa158015611792573d6000803e3d6000fd5b505050506040513d60208110156117a857600080fd5b505160ff169050600481108015906117c1575060128111155b610be65760405162461bcd60e51b81526004018080602001828103825260298152602001806135e76029913960400191505060405180910390fd5b6000808260000b13156118275761182083600084900b600a0a63ffffffff612e9416565b925061184f565b60008260000b121561184f5761184c836000848103900b600a0a63ffffffff612eed16565b92505b5090919050565b600080611869858563ffffffff612e9416565b905061187b818463ffffffff612eed16565b95945050505050565b603754600160a01b900460ff16156118d5576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561191a57600080fd5b505afa15801561192e573d6000803e3d6000fd5b505050506040513d602081101561194457600080fd5b50519050806119535750610bd9565b600061195d612cc0565b6042549091506001600160a01b0316801580159061197a57508282115b15611abc576000611991838563ffffffff612f2f16565b905060006119bc6127106119b060435485612e9490919063ffffffff16565b9063ffffffff612eed16565b90508082116119fc5760405162461bcd60e51b81526004018080602001828103825260228152602001806136316022913960400191505060405180910390fd5b8015611a7057603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015611a5757600080fd5b505af1158015611a6b573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0a57600080fd5b505afa158015611b1e573d6000803e3d6000fd5b505050506040513d6020811015611b3457600080fd5b5051925082821115611ba657603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611b8d57600080fd5b505af1158015611ba1573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611c05908590612f71565b50505050565b6000611c15613129565b905080611c225750610bd9565b6000611c2c613219565b90506000611c40838363ffffffff612df716565b9050600082611c6c57603954611c6590670de0b6b3a76400009063ffffffff612f2f16565b9050611cb8565b611c85846119b084603954612e9490919063ffffffff16565b905080670de0b6b3a76400001115611caf57611c65670de0b6b3a76400008263ffffffff612f2f16565b50505050610bd9565b80611cc65750505050610bd9565b60005b603454811015611e5557600060348281548110611ce257fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611d3557600080fd5b505afa158015611d49573d6000803e3d6000fd5b505050506040513d6020811015611d5f57600080fd5b5051905080611d6f575050611e4d565b6000611d81828663ffffffff61326b16565b6001600160a01b03808516600090815260406020819052902054919250168015801590611dae5750600082115b15611e485780611dce6001600160a01b038616828563ffffffff61328016565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611e2e57600080fd5b505af1158015611e42573d6000803e3d6000fd5b50505050505b505050505b600101611cc9565b5060005b60365481101561212757600060368281548110611e7257fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b158015611ebf57600080fd5b505afa158015611ed3573d6000803e3d6000fd5b505050506040513d6020811015611ee957600080fd5b505190506001600160a01b0381161561211d576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b158015611f3757600080fd5b505afa158015611f4b573d6000803e3d6000fd5b505050506040513d6020811015611f6157600080fd5b5051905080611ff057306001600160a01b0316630e5c011e60368681548110611f8657fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b158015611fd357600080fd5b505af1158015611fe7573d6000803e3d6000fd5b5050505061211b565b60008290506000816001600160a01b03166370a082316036888154811061201357fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561206157600080fd5b505afa158015612075573d6000803e3d6000fd5b505050506040513d602081101561208b57600080fd5b5051905082811061211857306001600160a01b0316630e5c011e603688815481106120b257fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b1580156120ff57600080fd5b505af1158015612113573d6000803e3d6000fd5b505050505b50505b505b5050600101611e59565b50604260009054906101000a90046001600160a01b03166001600160a01b0316638119c0656040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561217857600080fd5b505af115801561218c573d6000803e3d6000fd5b5050505050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116612216576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661222861171d565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3612266816132d2565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156122b457600080fd5b505afa1580156122c8573d6000803e3d6000fd5b505050506040513d60208110156122de57600080fd5b5051915060005b603654811015612423576000603682815481106122fe57fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561235457600080fd5b505afa158015612368573d6000803e3d6000fd5b505050506040513d602081101561237e57600080fd5b50511561241a57612417816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156123de57600080fd5b505afa1580156123f2573d6000803e3d6000fd5b505050506040513d602081101561240857600080fd5b5051859063ffffffff612df716565b93505b506001016122e5565b5050919050565b60606000612436610ed8565b905060606124446001612ce1565b9050606082604051908082528060200260200182016040528015612472578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156124a1578160200160208202803883390190505b5060408051868152602080880282010190915290915060009081908680156124d3578160200160208202803883390190505b50603854909750156125125760006124fc6127106119b06038548c612e9490919063ffffffff16565b905061250e898263ffffffff612f2f16565b9850505b60005b6034548110156125c257600061254b6034838154811061253157fe5b6000918252602090912001546001600160a01b0316612269565b9050600061255f603484815481106113cf57fe5b90508187848151811061256e57fe5b6020026020010181815250508086848151811061258757fe5b60209081029190910101526125b66125a983601284900363ffffffff6117fc16565b869063ffffffff612df716565b94505050600101612515565b5060005b6034548110156126735760008682815181106125de57fe5b60200260200101519050670de0b6b3a76400008110156126035750670de0b6b3a76400005b6000612655856119b0846126498a888151811061261c57fe5b60200260200101516012038c898151811061263357fe5b60200260200101516117fc90919063ffffffff16565b9063ffffffff612e9416565b9050612667848263ffffffff612df716565b935050506001016125c6565b506000612686898363ffffffff6132f616565b905060005b6034548110156126de576126bf846119b0848985815181106126a957fe5b6020026020010151612e9490919063ffffffff16565b8982815181106126cb57fe5b602090810291909101015260010161268b565b5050505050505050919050565b60008211612740576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561278557600080fd5b505afa158015612799573d6000803e3d6000fd5b505050506040513d60208110156127af57600080fd5b5051905060006127bd612cc0565b604154909150156128785760006127da838363ffffffff6132f616565b9050604154670de0b6b3a7640000821161280b57612806670de0b6b3a76400008363ffffffff612f2f16565b612823565b61282382670de0b6b3a764000063ffffffff612f2f16565b1115612876576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810186905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160606128be8561242a565b905060005b603454811015612b54578181815181106128d957fe5b6020026020010151600014156128ee57612b4c565b6000603482815481106128fd57fe5b60009182526020909120015483516001600160a01b03909116915083908390811061292457fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561298257600080fd5b505afa158015612996573d6000803e3d6000fd5b505050506040513d60208110156129ac57600080fd5b5051106129e9576129e4338484815181106129c357fe5b6020026020010151836001600160a01b03166132809092919063ffffffff16565b612b4a565b600060406000603485815481106129fc57fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612b09576000819050806001600160a01b031663d9caed123360348781548110612a5157fe5b9060005260206000200160009054906101000a90046001600160a01b0316888881518110612a7b57fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612aeb57600080fd5b505af1158015612aff573d6000803e3d6000fd5b5050505050612b48565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b6001016128c3565b508315612c02576000805b8251811015612baa576000612b7a603483815481106113cf57fe5b9050612b9f612b928260120386858151811061263357fe5b849063ffffffff612df716565b925050600101612b5f565b5084811015612c00576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612c5557600080fd5b505af1158015612c69573d6000803e3d6000fd5b50505050603b5485118015612c885750603754600160a01b900460ff16155b15612c9557612c95611884565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612ccd613219565b612cd5613129565b9063ffffffff612df716565b6060612ceb610ed8565b604051908082528060200260200182016040528015612d14578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561242357612dd8600a836001600160a01b031663aea9107860348581548110612d5257fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015612da057600080fd5b505afa158015612db4573d6000803e3d6000fd5b505050506040513d6020811015612dca57600080fd5b50519063ffffffff6117fc16565b838281518110612de457fe5b6020908102919091010152600101612d27565b600082820183811015612e51576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612e8c57508115155b949350505050565b600082612ea357506000610be6565b82820282848281612eb057fe5b0414612e515760405162461bcd60e51b81526004018080602001828103825260218152602001806136106021913960400191505060405180910390fd5b6000612e5183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613323565b6000612e5183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506133c5565b612f83826001600160a01b0316612e58565b612fd4576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106130125780518252601f199092019160209182019101612ff3565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114613074576040519150601f19603f3d011682016040523d82523d6000602084013e613079565b606091505b5091509150816130d0576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611c05578080602001905160208110156130ec57600080fd5b5051611c055760405162461bcd60e51b815260040180806020018281038252602a815260200180613653602a913960400191505060405180910390fd5b6000805b6034548110156132155760006034828154811061314657fe5b6000918252602082200154603480546001600160a01b03909216935061317091859081106113cf57fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156131bc57600080fd5b505afa1580156131d0573d6000803e3d6000fd5b505050506040513d60208110156131e657600080fd5b50519050801561320a576132076125a982601285900363ffffffff6117fc16565b94505b50505060010161312d565b5090565b6000805b603654811015613215576132616132546036838154811061323a57fe5b6000918252602090912001546001600160a01b031661341f565b839063ffffffff612df716565b915060010161321d565b6000612e518383670de0b6b3a7640000611856565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611ba6908490612f71565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061331184670de0b6b3a764000063ffffffff612e9416565b9050612e8c818463ffffffff612eed16565b600081836133af5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561337457818101518382015260200161335c565b50505050905090810190601f1680156133a15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385816133bb57fe5b0495945050505050565b600081848411156134175760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561337457818101518382015260200161335c565b505050900390565b600081815b603454811015612423576000613440603483815481106113cf57fe5b9050826001600160a01b031663aa388af66034848154811061345e57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b1580156134ac57600080fd5b505afa1580156134c0573d6000803e3d6000fd5b505050506040513d60208110156134d657600080fd5b505115613599576000836001600160a01b0316635f515226603485815481106134fb57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561354957600080fd5b505afa15801561355d573d6000803e3d6000fd5b505050506040513d602081101561357357600080fd5b505190508015613597576135946125a982601285900363ffffffff6117fc16565b94505b505b5060010161342456fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820f5ce484058ce120d7bb6fefde3051498b9396da8f85e58bb4fb70cd2ed9251b264736f6c634300050b0032", "devdoc": { "methods": { "allocate()": { diff --git a/contracts/deployments/rinkeby/solcInputs/86605db9d81ca0a1790de251140fb0d9.json b/contracts/deployments/rinkeby/solcInputs/86605db9d81ca0a1790de251140fb0d9.json new file mode 100644 index 0000000000..2d521f56eb --- /dev/null +++ b/contracts/deployments/rinkeby/solcInputs/86605db9d81ca0a1790de251140fb0d9.json @@ -0,0 +1,311 @@ +{ + "language": "Solidity", + "sources": { + "contracts/buyback/Buyback.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { Governable } from \"../governance/Governable.sol\";\n\nimport { IUniswapV2Router } from \"../interfaces/uniswap/IUniswapV2Router02.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract Buyback is Governable {\n using SafeERC20 for IERC20;\n\n event UniswapUpdated(address _address);\n\n // Address of Uniswap\n address public uniswapAddr = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;\n\n // Address of OUSD Vault\n address constant public vaultAddr = 0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70;\n\n // Swap from OUSD\n IERC20 constant ousd = IERC20(0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86);\n\n // Swap to OGN\n IERC20 constant ogn = IERC20(0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26);\n\n // USDT for Uniswap path\n IERC20 constant usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n /**\n * @dev Verifies that the caller is the OUSD Vault.\n */\n modifier onlyVault() {\n require(vaultAddr == msg.sender, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @dev Set address of Uniswap for performing liquidation of strategy reward\n * tokens. Setting to 0x0 will pause swaps.\n * @param _address Address of Uniswap\n */\n function setUniswapAddr(address _address) external onlyGovernor {\n uniswapAddr = _address;\n // Give Uniswap unlimited OUSD allowance\n ousd.safeApprove(uniswapAddr, 0);\n ousd.safeApprove(uniswapAddr, uint256(-1));\n emit UniswapUpdated(_address);\n }\n\n /**\n * @dev Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible\n * protocol (e.g. Sushiswap)\n **/\n function swap() external onlyVault {\n if (uniswapAddr == address(0)) return;\n\n uint256 sourceAmount = ousd.balanceOf(address(this));\n if (sourceAmount < 1000 * 1e18) return;\n\n // Uniswap redemption path\n address[] memory path = new address[](4);\n path[0] = address(ousd);\n path[1] = address(usdt);\n path[2] = IUniswapV2Router(uniswapAddr).WETH();\n path[3] = address(ogn);\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\n sourceAmount,\n uint256(0),\n path,\n address(this),\n now\n );\n }\n\n /**\n * @notice Owner function to withdraw a specific amount of a token\n */\n function transferToken(address token, uint256 amount)\n external\n onlyGovernor\n nonReentrant\n {\n IERC20(token).safeTransfer(_governor(), amount);\n }\n}\n" + }, + "contracts/governance/Governable.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Governable Contract\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\n * from owner to governor and renounce methods removed. Does not use\n * Context.sol like Ownable.sol does for simplification.\n * @author Origin Protocol Inc\n */\ncontract Governable {\n // Storage position of the owner and pendingOwner of the contract\n // keccak256(\"OUSD.governor\");\n bytes32\n private constant governorPosition = 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\n\n // keccak256(\"OUSD.pending.governor\");\n bytes32\n private constant pendingGovernorPosition = 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\n\n // keccak256(\"OUSD.reentry.status\");\n bytes32\n private constant reentryStatusPosition = 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\n\n // See OpenZeppelin ReentrancyGuard implementation\n uint256 constant _NOT_ENTERED = 1;\n uint256 constant _ENTERED = 2;\n\n event PendingGovernorshipTransfer(\n address indexed previousGovernor,\n address indexed newGovernor\n );\n\n event GovernorshipTransferred(\n address indexed previousGovernor,\n address indexed newGovernor\n );\n\n /**\n * @dev Initializes the contract setting the deployer as the initial Governor.\n */\n constructor() internal {\n _setGovernor(msg.sender);\n emit GovernorshipTransferred(address(0), _governor());\n }\n\n /**\n * @dev Returns the address of the current Governor.\n */\n function governor() public view returns (address) {\n return _governor();\n }\n\n /**\n * @dev Returns the address of the current Governor.\n */\n function _governor() internal view returns (address governorOut) {\n bytes32 position = governorPosition;\n assembly {\n governorOut := sload(position)\n }\n }\n\n /**\n * @dev Returns the address of the pending Governor.\n */\n function _pendingGovernor()\n internal\n view\n returns (address pendingGovernor)\n {\n bytes32 position = pendingGovernorPosition;\n assembly {\n pendingGovernor := sload(position)\n }\n }\n\n /**\n * @dev Throws if called by any account other than the Governor.\n */\n modifier onlyGovernor() {\n require(isGovernor(), \"Caller is not the Governor\");\n _;\n }\n\n /**\n * @dev Returns true if the caller is the current Governor.\n */\n function isGovernor() public view returns (bool) {\n return msg.sender == _governor();\n }\n\n function _setGovernor(address newGovernor) internal {\n bytes32 position = governorPosition;\n assembly {\n sstore(position, newGovernor)\n }\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n bytes32 position = reentryStatusPosition;\n uint256 _reentry_status;\n assembly {\n _reentry_status := sload(position)\n }\n\n // On the first call to nonReentrant, _notEntered will be true\n require(_reentry_status != _ENTERED, \"Reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n assembly {\n sstore(position, _ENTERED)\n }\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n assembly {\n sstore(position, _NOT_ENTERED)\n }\n }\n\n function _setPendingGovernor(address newGovernor) internal {\n bytes32 position = pendingGovernorPosition;\n assembly {\n sstore(position, newGovernor)\n }\n }\n\n /**\n * @dev Transfers Governance of the contract to a new account (`newGovernor`).\n * Can only be called by the current Governor. Must be claimed for this to complete\n * @param _newGovernor Address of the new Governor\n */\n function transferGovernance(address _newGovernor) external onlyGovernor {\n _setPendingGovernor(_newGovernor);\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\n }\n\n /**\n * @dev Claim Governance of the contract to a new account (`newGovernor`).\n * Can only be called by the new Governor.\n */\n function claimGovernance() external {\n require(\n msg.sender == _pendingGovernor(),\n \"Only the pending Governor can complete the claim\"\n );\n _changeGovernor(msg.sender);\n }\n\n /**\n * @dev Change Governance of the contract to a new account (`newGovernor`).\n * @param _newGovernor Address of the new Governor\n */\n function _changeGovernor(address _newGovernor) internal {\n require(_newGovernor != address(0), \"New Governor is address(0)\");\n emit GovernorshipTransferred(_governor(), _newGovernor);\n _setGovernor(_newGovernor);\n }\n}\n" + }, + "contracts/interfaces/uniswap/IUniswapV2Router02.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IUniswapV2Router {\n function WETH() external pure returns (address);\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n );\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\n * the optional functions; to access them see {ERC20Detailed}.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.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 ERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function callOptionalReturn(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.\n\n // A Solidity high level call has three parts:\n // 1. The target address is checked to verify it contains contract code\n // 2. The call itself is made, and success asserted\n // 3. The return value is decoded, which in turn checks the size of the returned data.\n // solhint-disable-next-line max-line-length\n require(address(token).isContract(), \"SafeERC20: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = address(token).call(data);\n require(success, \"SafeERC20: low-level call failed\");\n\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction overflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot overflow.\n *\n * _Available since v2.4.0._\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n *\n * _Available since v2.4.0._\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n *\n * _Available since v2.4.0._\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "pragma solidity ^0.5.5;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following \n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\n // for accounts without code, i.e. `keccak256('')`\n bytes32 codehash;\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n // solhint-disable-next-line no-inline-assembly\n assembly { codehash := extcodehash(account) }\n return (codehash != accountHash && codehash != 0x0);\n }\n\n /**\n * @dev Converts an `address` into `address payable`. Note that this is\n * simply a type cast: the actual underlying value is not changed.\n *\n * _Available since v2.4.0._\n */\n function toPayable(address account) internal pure returns (address payable) {\n return address(uint160(account));\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 * _Available since v2.4.0._\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-call-value\n (bool success, ) = recipient.call.value(amount)(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n}\n" + }, + "contracts/utils/InitializableAbstractStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\nimport { Governable } from \"../governance/Governable.sol\";\n\ncontract InitializableAbstractStrategy is Initializable, Governable {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n event PTokenAdded(address indexed _asset, address _pToken);\n event PTokenRemoved(address indexed _asset, address _pToken);\n event Deposit(address indexed _asset, address _pToken, uint256 _amount);\n event Withdrawal(address indexed _asset, address _pToken, uint256 _amount);\n event RewardTokenCollected(address recipient, uint256 amount);\n\n // Core address for the given platform\n address public platformAddress;\n\n address public vaultAddress;\n\n // asset => pToken (Platform Specific Token Address)\n mapping(address => address) public assetToPToken;\n\n // Full list of all assets supported here\n address[] internal assetsMapped;\n\n // Reward token address\n address public rewardTokenAddress;\n uint256 public rewardLiquidationThreshold;\n\n /**\n * @dev Internal initialize function, to set up initial internal state\n * @param _platformAddress jGeneric platform address\n * @param _vaultAddress Address of the Vault\n * @param _rewardTokenAddress Address of reward token for platform\n * @param _assets Addresses of initial supported assets\n * @param _pTokens Platform Token corresponding addresses\n */\n function initialize(\n address _platformAddress,\n address _vaultAddress,\n address _rewardTokenAddress,\n address[] calldata _assets,\n address[] calldata _pTokens\n ) external onlyGovernor initializer {\n InitializableAbstractStrategy._initialize(\n _platformAddress,\n _vaultAddress,\n _rewardTokenAddress,\n _assets,\n _pTokens\n );\n }\n\n function _initialize(\n address _platformAddress,\n address _vaultAddress,\n address _rewardTokenAddress,\n address[] memory _assets,\n address[] memory _pTokens\n ) internal {\n platformAddress = _platformAddress;\n vaultAddress = _vaultAddress;\n rewardTokenAddress = _rewardTokenAddress;\n uint256 assetCount = _assets.length;\n require(assetCount == _pTokens.length, \"Invalid input arrays\");\n for (uint256 i = 0; i < assetCount; i++) {\n _setPTokenAddress(_assets[i], _pTokens[i]);\n }\n }\n\n /**\n * @dev Collect accumulated reward token and send to Vault.\n */\n function collectRewardToken() external onlyVault nonReentrant {\n IERC20 rewardToken = IERC20(rewardTokenAddress);\n uint256 balance = rewardToken.balanceOf(address(this));\n emit RewardTokenCollected(vaultAddress, balance);\n rewardToken.safeTransfer(vaultAddress, balance);\n }\n\n /**\n * @dev Verifies that the caller is the Vault.\n */\n modifier onlyVault() {\n require(msg.sender == vaultAddress, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @dev Verifies that the caller is the Vault or Governor.\n */\n modifier onlyVaultOrGovernor() {\n require(\n msg.sender == vaultAddress || msg.sender == governor(),\n \"Caller is not the Vault or Governor\"\n );\n _;\n }\n\n /**\n * @dev Set the reward token address.\n * @param _rewardTokenAddress Address of the reward token\n */\n function setRewardTokenAddress(address _rewardTokenAddress)\n external\n onlyGovernor\n {\n rewardTokenAddress = _rewardTokenAddress;\n }\n\n /**\n * @dev Set the reward token liquidation threshold.\n * @param _threshold Threshold amount in decimals of reward token that will\n * cause the Vault to claim and withdrawAll on allocate() calls.\n */\n function setRewardLiquidationThreshold(uint256 _threshold)\n external\n onlyGovernor\n {\n rewardLiquidationThreshold = _threshold;\n }\n\n /**\n * @dev Provide support for asset by passing its pToken address.\n * This method can only be called by the system Governor\n * @param _asset Address for the asset\n * @param _pToken Address for the corresponding platform token\n */\n function setPTokenAddress(address _asset, address _pToken)\n external\n onlyGovernor\n {\n _setPTokenAddress(_asset, _pToken);\n }\n\n /**\n * @dev Remove a supported asset by passing its index.\n * This method can only be called by the system Governor\n * @param _assetIndex Index of the asset to be removed\n */\n function removePToken(uint256 _assetIndex) external onlyGovernor {\n require(_assetIndex < assetsMapped.length, \"Invalid index\");\n address asset = assetsMapped[_assetIndex];\n address pToken = assetToPToken[asset];\n\n if (_assetIndex < assetsMapped.length - 1) {\n assetsMapped[_assetIndex] = assetsMapped[assetsMapped.length - 1];\n }\n assetsMapped.pop();\n assetToPToken[asset] = address(0);\n\n emit PTokenRemoved(asset, pToken);\n }\n\n /**\n * @dev Provide support for asset by passing its pToken address.\n * Add to internal mappings and execute the platform specific,\n * abstract method `_abstractSetPToken`\n * @param _asset Address for the asset\n * @param _pToken Address for the corresponding platform token\n */\n function _setPTokenAddress(address _asset, address _pToken) internal {\n require(assetToPToken[_asset] == address(0), \"pToken already set\");\n require(\n _asset != address(0) && _pToken != address(0),\n \"Invalid addresses\"\n );\n\n assetToPToken[_asset] = _pToken;\n assetsMapped.push(_asset);\n\n emit PTokenAdded(_asset, _pToken);\n\n _abstractSetPToken(_asset, _pToken);\n }\n\n /**\n * @dev Transfer token to governor. Intended for recovering tokens stuck in\n * strategy contracts, i.e. mistaken sends.\n * @param _asset Address for the asset\n * @param _amount Amount of the asset to transfer\n */\n function transferToken(address _asset, uint256 _amount)\n public\n onlyGovernor\n {\n IERC20(_asset).safeTransfer(governor(), _amount);\n }\n\n /***************************************\n Abstract\n ****************************************/\n\n function _abstractSetPToken(address _asset, address _pToken) internal;\n\n function safeApproveAllTokens() external;\n\n /**\n * @dev Deposit a amount of asset into the platform\n * @param _asset Address for the asset\n * @param _amount Units of asset to deposit\n */\n function deposit(address _asset, uint256 _amount) external;\n\n /**\n * @dev Deposit balance of all supported assets into the platform\n */\n function depositAll() external;\n\n /**\n * @dev Withdraw an amount of asset from the platform.\n * @param _recipient Address to which the asset should be sent\n * @param _asset Address of the asset\n * @param _amount Units of asset to withdraw\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external;\n\n /**\n * @dev Withdraw all assets from strategy sending assets to Vault.\n */\n function withdrawAll() external;\n\n /**\n * @dev Get the total asset value held in the platform.\n * This includes any interest that was generated since depositing.\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance);\n\n /**\n * @dev Check if an asset is supported.\n * @param _asset Address of the asset\n * @return bool Whether asset is supported\n */\n function supportsAsset(address _asset) external view returns (bool);\n}\n" + }, + "@openzeppelin/upgrades/contracts/Initializable.sol": { + "content": "pragma solidity >=0.4.24 <0.7.0;\n\n\n/**\n * @title Initializable\n *\n * @dev Helper contract to support initializer functions. To use it, replace\n * the constructor with a function that has the `initializer` modifier.\n * WARNING: Unlike constructors, initializer functions must be manually\n * invoked. This applies both to deploying an Initializable contract, as well\n * as extending an Initializable contract via inheritance.\n * WARNING: When used with inheritance, manual care must be taken to not invoke\n * a parent initializer twice, or ensure that all initializers are idempotent,\n * because this is not dealt with automatically as with constructors.\n */\ncontract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private initializing;\n\n /**\n * @dev Modifier to use in the initializer function of a contract.\n */\n modifier initializer() {\n require(initializing || isConstructor() || !initialized, \"Contract instance has already been initialized\");\n\n bool isTopLevelCall = !initializing;\n if (isTopLevelCall) {\n initializing = true;\n initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function isConstructor() private view returns (bool) {\n // extcodesize checks the size of the code stored in an address, and\n // address returns the current address. Since the code is still not\n // deployed when running a constructor, any checks on its code size will\n // yield zero, making it an effective way to detect if a contract is\n // under construction or not.\n address self = address(this);\n uint256 cs;\n assembly { cs := extcodesize(self) }\n return cs == 0;\n }\n\n // Reserved storage space to allow for layout changes in the future.\n uint256[50] private ______gap;\n}\n" + }, + "contracts/strategies/ThreePoolStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title Curve 3Pool Strategy\n * @notice Investment strategy for investing stablecoins via Curve 3Pool\n * @author Origin Protocol Inc\n */\n\nimport { ICurvePool } from \"./ICurvePool.sol\";\nimport { ICurveGauge } from \"./ICurveGauge.sol\";\nimport { ICRVMinter } from \"./ICRVMinter.sol\";\nimport {\n IERC20,\n InitializableAbstractStrategy\n} from \"../utils/InitializableAbstractStrategy.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\nimport { Helpers } from \"../utils/Helpers.sol\";\n\ncontract ThreePoolStrategy is InitializableAbstractStrategy {\n using StableMath for uint256;\n\n event RewardTokenCollected(address recipient, uint256 amount);\n\n address crvGaugeAddress;\n address crvMinterAddress;\n uint256 constant maxSlippage = 1e16; // 1%, same as the Curve UI\n\n /**\n * Initializer for setting up strategy internal state. This overrides the\n * InitializableAbstractStrategy initializer as Curve strategies don't fit\n * well within that abstraction.\n * @param _platformAddress Address of the Curve 3pool\n * @param _vaultAddress Address of the vault\n * @param _rewardTokenAddress Address of CRV\n * @param _assets Addresses of supported assets. MUST be passed in the same\n * order as returned by coins on the pool contract, i.e.\n * DAI, USDC, USDT\n * @param _pTokens Platform Token corresponding addresses\n * @param _crvGaugeAddress Address of the Curve DAO gauge for this pool\n * @param _crvMinterAddress Address of the CRV minter for rewards\n */\n function initialize(\n address _platformAddress, // 3Pool address\n address _vaultAddress,\n address _rewardTokenAddress, // CRV\n address[] calldata _assets,\n address[] calldata _pTokens,\n address _crvGaugeAddress,\n address _crvMinterAddress\n ) external onlyGovernor initializer {\n // Should be set prior to abstract initialize call otherwise\n // abstractSetPToken calls will fail\n crvGaugeAddress = _crvGaugeAddress;\n crvMinterAddress = _crvMinterAddress;\n InitializableAbstractStrategy._initialize(\n _platformAddress,\n _vaultAddress,\n _rewardTokenAddress,\n _assets,\n _pTokens\n );\n }\n\n /**\n * @dev Collect accumulated CRV and send to Vault.\n */\n function collectRewardToken() external onlyVault nonReentrant {\n IERC20 crvToken = IERC20(rewardTokenAddress);\n ICRVMinter minter = ICRVMinter(crvMinterAddress);\n uint256 balance = crvToken.balanceOf(address(this));\n emit RewardTokenCollected(vaultAddress, balance);\n minter.mint(crvGaugeAddress);\n crvToken.safeTransfer(vaultAddress, balance);\n }\n\n /**\n * @dev Deposit asset into the Curve 3Pool\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n */\n function deposit(address _asset, uint256 _amount)\n external\n onlyVault\n nonReentrant\n {\n require(_amount > 0, \"Must deposit something\");\n emit Deposit(_asset, address(platformAddress), _amount);\n // 3Pool requires passing deposit amounts for all 3 assets, set to 0 for\n // all\n uint256[3] memory _amounts;\n uint256 poolCoinIndex = _getPoolCoinIndex(_asset);\n // Set the amount on the asset we want to deposit\n _amounts[poolCoinIndex] = _amount;\n ICurvePool curvePool = ICurvePool(platformAddress);\n uint256 assetDecimals = Helpers.getDecimals(_asset);\n uint256 depositValue = _amount\n .scaleBy(int8(18 - assetDecimals))\n .divPrecisely(curvePool.get_virtual_price());\n uint256 minMintAmount = depositValue.mulTruncate(\n uint256(1e18).sub(maxSlippage)\n );\n // Do the deposit to 3pool\n curvePool.add_liquidity(_amounts, minMintAmount);\n // Deposit into Gauge\n IERC20 pToken = IERC20(assetToPToken[_asset]);\n ICurveGauge(crvGaugeAddress).deposit(\n pToken.balanceOf(address(this)),\n address(this)\n );\n }\n\n /**\n * @dev Deposit the entire balance of any supported asset into the Curve 3pool\n */\n function depositAll() external onlyVault nonReentrant {\n uint256[3] memory _amounts = [uint256(0), uint256(0), uint256(0)];\n uint256 depositValue = 0;\n ICurvePool curvePool = ICurvePool(platformAddress);\n\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n address assetAddress = assetsMapped[i];\n uint256 balance = IERC20(assetAddress).balanceOf(address(this));\n if (balance > 0) {\n uint256 poolCoinIndex = _getPoolCoinIndex(assetAddress);\n // Set the amount on the asset we want to deposit\n _amounts[poolCoinIndex] = balance;\n uint256 assetDecimals = Helpers.getDecimals(assetAddress);\n // Get value of deposit in Curve LP token to later determine\n // the minMintAmount argument for add_liquidity\n depositValue = depositValue.add(\n balance.scaleBy(int8(18 - assetDecimals)).divPrecisely(\n curvePool.get_virtual_price()\n )\n );\n emit Deposit(assetAddress, address(platformAddress), balance);\n }\n }\n\n uint256 minMintAmount = depositValue.mulTruncate(\n uint256(1e18).sub(maxSlippage)\n );\n // Do the deposit to 3pool\n curvePool.add_liquidity(_amounts, minMintAmount);\n // Deposit into Gauge, the PToken is the same (3Crv) for all mapped\n // assets, so just get the address from the first one\n IERC20 pToken = IERC20(assetToPToken[assetsMapped[0]]);\n ICurveGauge(crvGaugeAddress).deposit(\n pToken.balanceOf(address(this)),\n address(this)\n );\n }\n\n /**\n * @dev Withdraw asset from Curve 3Pool\n * @param _recipient Address to receive withdrawn asset\n * @param _asset Address of asset to withdraw\n * @param _amount Amount of asset to withdraw\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external onlyVault nonReentrant {\n require(_recipient != address(0), \"Invalid recipient\");\n require(_amount > 0, \"Invalid amount\");\n\n emit Withdrawal(_asset, address(assetToPToken[_asset]), _amount);\n\n // Calculate how much of the pool token we need to withdraw\n (uint256 contractPTokens, , uint256 totalPTokens) = _getTotalPTokens();\n\n require(totalPTokens > 0, \"Insufficient 3CRV balance\");\n\n uint256 poolCoinIndex = _getPoolCoinIndex(_asset);\n // Calculate the max amount of the asset we'd get if we withdrew all the\n // platform tokens\n ICurvePool curvePool = ICurvePool(platformAddress);\n uint256 maxAmount = curvePool.calc_withdraw_one_coin(\n totalPTokens,\n int128(poolCoinIndex)\n );\n\n // Calculate how many platform tokens we need to withdraw the asset amount\n uint256 withdrawPTokens = totalPTokens.mul(_amount).div(maxAmount);\n if (contractPTokens < withdrawPTokens) {\n // Not enough of pool token exists on this contract, some must be\n // staked in Gauge, unstake difference\n ICurveGauge(crvGaugeAddress).withdraw(\n withdrawPTokens.sub(contractPTokens)\n );\n }\n\n // Calculate a minimum withdrawal amount\n uint256 assetDecimals = Helpers.getDecimals(_asset);\n // 3crv is 1e18, subtract slippage percentage and scale to asset\n // decimals\n uint256 minWithdrawAmount = withdrawPTokens\n .mulTruncate(uint256(1e18).sub(maxSlippage))\n .scaleBy(int8(assetDecimals - 18));\n\n curvePool.remove_liquidity_one_coin(\n withdrawPTokens,\n int128(poolCoinIndex),\n minWithdrawAmount\n );\n IERC20(_asset).safeTransfer(_recipient, _amount);\n\n // Transfer any leftover dust back to the vault buffer.\n uint256 dust = IERC20(_asset).balanceOf(address(this));\n if (dust > 0) {\n IERC20(_asset).safeTransfer(vaultAddress, dust);\n }\n }\n\n /**\n * @dev Remove all assets from platform and send them to Vault contract.\n */\n function withdrawAll() external onlyVaultOrGovernor nonReentrant {\n // Withdraw all from Gauge\n (, uint256 gaugePTokens, uint256 totalPTokens) = _getTotalPTokens();\n ICurveGauge(crvGaugeAddress).withdraw(gaugePTokens);\n uint256[3] memory minWithdrawAmounts = [\n uint256(0),\n uint256(0),\n uint256(0)\n ];\n // Calculate min withdrawal amounts for each coin\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n address assetAddress = assetsMapped[i];\n uint256 virtualBalance = checkBalance(assetAddress);\n uint256 poolCoinIndex = _getPoolCoinIndex(assetAddress);\n minWithdrawAmounts[poolCoinIndex] = virtualBalance.mulTruncate(\n uint256(1e18).sub(maxSlippage)\n );\n }\n // Remove liqudiity\n ICurvePool threePool = ICurvePool(platformAddress);\n threePool.remove_liquidity(totalPTokens, minWithdrawAmounts);\n // Transfer assets out ot Vault\n // Note that Curve will provide all 3 of the assets in 3pool even if\n // we have not set PToken addresses for all of them in this strategy\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n IERC20 asset = IERC20(threePool.coins(i));\n asset.safeTransfer(vaultAddress, asset.balanceOf(address(this)));\n }\n }\n\n /**\n * @dev Get the total asset value held in the platform\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n public\n view\n returns (uint256 balance)\n {\n require(assetToPToken[_asset] != address(0), \"Unsupported asset\");\n // LP tokens in this contract. This should generally be nothing as we\n // should always stake the full balance in the Gauge, but include for\n // safety\n (, , uint256 totalPTokens) = _getTotalPTokens();\n ICurvePool curvePool = ICurvePool(platformAddress);\n\n uint256 pTokenTotalSupply = IERC20(assetToPToken[_asset]).totalSupply();\n if (pTokenTotalSupply > 0) {\n uint256 curveBalance = IERC20(_asset).balanceOf(address(curvePool));\n if (curveBalance > 0) {\n balance = totalPTokens.mul(curveBalance).div(pTokenTotalSupply);\n }\n }\n }\n\n /**\n * @dev Retuns bool indicating whether asset is supported by strategy\n * @param _asset Address of the asset\n */\n function supportsAsset(address _asset) external view returns (bool) {\n return assetToPToken[_asset] != address(0);\n }\n\n /**\n * @dev Approve the spending of all assets by their corresponding pool tokens,\n * if for some reason is it necessary.\n */\n function safeApproveAllTokens() external {\n // This strategy is a special case since it only supports one asset\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n _abstractSetPToken(assetsMapped[i], assetToPToken[assetsMapped[i]]);\n }\n }\n\n /**\n * @dev Calculate the total platform token balance (i.e. 3CRV) that exist in\n * this contract or is staked in the Gauge (or in other words, the total\n * amount platform tokens we own).\n * @return totalPTokens Total amount of platform tokens in native decimals\n */\n function _getTotalPTokens()\n internal\n view\n returns (\n uint256 contractPTokens,\n uint256 gaugePTokens,\n uint256 totalPTokens\n )\n {\n contractPTokens = IERC20(assetToPToken[assetsMapped[0]]).balanceOf(\n address(this)\n );\n ICurveGauge gauge = ICurveGauge(crvGaugeAddress);\n gaugePTokens = gauge.balanceOf(address(this));\n totalPTokens = contractPTokens.add(gaugePTokens);\n }\n\n /**\n * @dev Call the necessary approvals for the Curve pool and gauge\n * @param _asset Address of the asset\n * @param _pToken Address of the corresponding platform token (i.e. 3CRV)\n */\n function _abstractSetPToken(address _asset, address _pToken) internal {\n IERC20 asset = IERC20(_asset);\n IERC20 pToken = IERC20(_pToken);\n // 3Pool for asset (required for adding liquidity)\n asset.safeApprove(platformAddress, 0);\n asset.safeApprove(platformAddress, uint256(-1));\n // 3Pool for LP token (required for removing liquidity)\n pToken.safeApprove(platformAddress, 0);\n pToken.safeApprove(platformAddress, uint256(-1));\n // Gauge for LP token\n pToken.safeApprove(crvGaugeAddress, 0);\n pToken.safeApprove(crvGaugeAddress, uint256(-1));\n }\n\n /**\n * @dev Get the index of the coin in 3pool\n */\n function _getPoolCoinIndex(address _asset) internal view returns (uint256) {\n for (uint256 i = 0; i < 3; i++) {\n if (assetsMapped[i] == _asset) return i;\n }\n revert(\"Invalid 3pool asset\");\n }\n}\n" + }, + "contracts/strategies/ICurvePool.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface ICurvePool {\n function get_virtual_price() external view returns (uint256);\n\n function add_liquidity(uint256[3] calldata _amounts, uint256 _min) external;\n\n function calc_token_amount(uint256[3] calldata _amounts, bool _deposit)\n external\n returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 _amount,\n int128 _index,\n uint256 _minAmount\n ) external;\n\n function remove_liquidity(\n uint256 _amount,\n uint256[3] calldata _minWithdrawAmounts\n ) external;\n\n function calc_withdraw_one_coin(uint256 _amount, int128 _index)\n external\n view\n returns (uint256);\n\n function coins(uint256 _index) external view returns (address);\n}\n" + }, + "contracts/strategies/ICurveGauge.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface ICurveGauge {\n function balanceOf(address account) external view returns (uint256);\n\n function deposit(uint256 value, address account) external;\n\n function withdraw(uint256 value) external;\n}\n" + }, + "contracts/strategies/ICRVMinter.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface ICRVMinter {\n function mint(address gaugeAddress) external;\n}\n" + }, + "contracts/utils/StableMath.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n// Based on StableMath from Stability Labs Pty. Ltd.\n// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol\n\nlibrary StableMath {\n using SafeMath for uint256;\n\n /**\n * @dev Scaling unit for use in specific calculations,\n * where 1 * 10**18, or 1e18 represents a unit '1'\n */\n uint256 private constant FULL_SCALE = 1e18;\n\n /***************************************\n Helpers\n ****************************************/\n\n /**\n * @dev Adjust the scale of an integer\n * @param adjustment Amount to adjust by e.g. scaleBy(1e18, -1) == 1e17\n */\n function scaleBy(uint256 x, int8 adjustment)\n internal\n pure\n returns (uint256)\n {\n if (adjustment > 0) {\n x = x.mul(10**uint256(adjustment));\n } else if (adjustment < 0) {\n x = x.div(10**uint256(adjustment * -1));\n }\n return x;\n }\n\n /***************************************\n Precise Arithmetic\n ****************************************/\n\n /**\n * @dev Multiplies two precise units, and then truncates by the full scale\n * @param x Left hand input to multiplication\n * @param y Right hand input to multiplication\n * @return Result after multiplying the two inputs and then dividing by the shared\n * scale unit\n */\n function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {\n return mulTruncateScale(x, y, FULL_SCALE);\n }\n\n /**\n * @dev Multiplies two precise units, and then truncates by the given scale. For example,\n * when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18\n * @param x Left hand input to multiplication\n * @param y Right hand input to multiplication\n * @param scale Scale unit\n * @return Result after multiplying the two inputs and then dividing by the shared\n * scale unit\n */\n function mulTruncateScale(\n uint256 x,\n uint256 y,\n uint256 scale\n ) internal pure returns (uint256) {\n // e.g. assume scale = fullScale\n // z = 10e18 * 9e17 = 9e36\n uint256 z = x.mul(y);\n // return 9e38 / 1e18 = 9e18\n return z.div(scale);\n }\n\n /**\n * @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result\n * @param x Left hand input to multiplication\n * @param y Right hand input to multiplication\n * @return Result after multiplying the two inputs and then dividing by the shared\n * scale unit, rounded up to the closest base unit.\n */\n function mulTruncateCeil(uint256 x, uint256 y)\n internal\n pure\n returns (uint256)\n {\n // e.g. 8e17 * 17268172638 = 138145381104e17\n uint256 scaled = x.mul(y);\n // e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17\n uint256 ceil = scaled.add(FULL_SCALE.sub(1));\n // e.g. 13814538111.399...e18 / 1e18 = 13814538111\n return ceil.div(FULL_SCALE);\n }\n\n /**\n * @dev Precisely divides two units, by first scaling the left hand operand. Useful\n * for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)\n * @param x Left hand input to division\n * @param y Right hand input to division\n * @return Result after multiplying the left operand by the scale, and\n * executing the division on the right hand input.\n */\n function divPrecisely(uint256 x, uint256 y)\n internal\n pure\n returns (uint256)\n {\n // e.g. 8e18 * 1e18 = 8e36\n uint256 z = x.mul(FULL_SCALE);\n // e.g. 8e36 / 10e18 = 8e17\n return z.div(y);\n }\n}\n" + }, + "contracts/utils/Helpers.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IBasicToken } from \"../interfaces/IBasicToken.sol\";\n\nlibrary Helpers {\n /**\n * @notice Fetch the `symbol()` from an ERC20 token\n * @dev Grabs the `symbol()` from a contract\n * @param _token Address of the ERC20 token\n * @return string Symbol of the ERC20 token\n */\n function getSymbol(address _token) internal view returns (string memory) {\n string memory symbol = IBasicToken(_token).symbol();\n return symbol;\n }\n\n /**\n * @notice Fetch the `decimals()` from an ERC20 token\n * @dev Grabs the `decimals()` from a contract and fails if\n * the decimal value does not live within a certain range\n * @param _token Address of the ERC20 token\n * @return uint256 Decimals of the ERC20 token\n */\n function getDecimals(address _token) internal view returns (uint256) {\n uint256 decimals = IBasicToken(_token).decimals();\n require(\n decimals >= 4 && decimals <= 18,\n \"Token must have sufficient decimal places\"\n );\n\n return decimals;\n }\n}\n" + }, + "contracts/interfaces/IBasicToken.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IBasicToken {\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/vault/VaultStorage.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD VaultStorage Contract\n * @notice The VaultStorage contract defines the storage for the Vault contracts\n * @author Origin Protocol Inc\n */\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport { IStrategy } from \"../interfaces/IStrategy.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\nimport { OUSD } from \"../token/OUSD.sol\";\nimport \"../utils/Helpers.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\n\ncontract VaultStorage is Initializable, Governable {\n using SafeMath for uint256;\n using StableMath for uint256;\n using SafeMath for int256;\n using SafeERC20 for IERC20;\n\n event AssetSupported(address _asset);\n event AssetDefaultStrategyUpdated(address _asset, address _strategy);\n event StrategyApproved(address _addr);\n event StrategyRemoved(address _addr);\n event Mint(address _addr, uint256 _value);\n event Redeem(address _addr, uint256 _value);\n event CapitalPaused();\n event CapitalUnpaused();\n event RebasePaused();\n event RebaseUnpaused();\n event VaultBufferUpdated(uint256 _vaultBuffer);\n event RedeemFeeUpdated(uint256 _redeemFeeBps);\n event PriceProviderUpdated(address _priceProvider);\n event AllocateThresholdUpdated(uint256 _threshold);\n event RebaseThresholdUpdated(uint256 _threshold);\n event UniswapUpdated(address _address);\n event StrategistUpdated(address _address);\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\n event TrusteeFeeBpsChanged(uint256 _basis);\n event TrusteeAddressChanged(address _address);\n\n // Assets supported by the Vault, i.e. Stablecoins\n struct Asset {\n bool isSupported;\n }\n mapping(address => Asset) assets;\n address[] allAssets;\n\n // Strategies approved for use by the Vault\n struct Strategy {\n bool isSupported;\n uint256 _deprecated; // Deprecated storage slot\n }\n mapping(address => Strategy) strategies;\n address[] allStrategies;\n\n // Address of the Oracle price provider contract\n address public priceProvider;\n // Pausing bools\n bool public rebasePaused = false;\n bool public capitalPaused = true;\n // Redemption fee in basis points\n uint256 public redeemFeeBps;\n // Buffer of assets to keep in Vault to handle (most) withdrawals\n uint256 public vaultBuffer;\n // Mints over this amount automatically allocate funds. 18 decimals.\n uint256 public autoAllocateThreshold;\n // Mints over this amount automatically rebase. 18 decimals.\n uint256 public rebaseThreshold;\n\n OUSD oUSD;\n\n //keccak256(\"OUSD.vault.governor.admin.impl\");\n bytes32 constant adminImplPosition = 0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;\n\n // Address of the contract responsible for post rebase syncs with AMMs\n address private _deprecated_rebaseHooksAddr = address(0);\n\n // Address of Uniswap\n address public uniswapAddr = address(0);\n\n // Address of the Strategist\n address public strategistAddr = address(0);\n\n // Mapping of asset address to the Strategy that they should automatically\n // be allocated to\n mapping(address => address) public assetDefaultStrategies;\n\n uint256 public maxSupplyDiff;\n\n // Trustee contract that can collect a percentage of yield\n address public trusteeAddress;\n\n // Amount of yield collected in basis points\n uint256 public trusteeFeeBps;\n\n /**\n * @dev set the implementation for the admin, this needs to be in a base class else we cannot set it\n * @param newImpl address of the implementation\n */\n function setAdminImpl(address newImpl) external onlyGovernor {\n require(\n Address.isContract(newImpl),\n \"new implementation is not a contract\"\n );\n bytes32 position = adminImplPosition;\n assembly {\n sstore(position, newImpl)\n }\n }\n}\n" + }, + "contracts/interfaces/IStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\n */\ninterface IStrategy {\n /**\n * @dev Deposit the given asset to platform\n * @param _asset asset address\n * @param _amount Amount to deposit\n */\n function deposit(address _asset, uint256 _amount) external;\n\n /**\n * @dev Deposit the entire balance of all supported assets in the Strategy\n * to the platform\n */\n function depositAll() external;\n\n /**\n * @dev Withdraw given asset from Lending platform\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external;\n\n /**\n * @dev Liquidate all assets in strategy and return them to Vault.\n */\n function withdrawAll() external;\n\n /**\n * @dev Returns the current balance of the given asset.\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance);\n\n /**\n * @dev Returns bool indicating whether strategy supports asset.\n */\n function supportsAsset(address _asset) external view returns (bool);\n\n /**\n * @dev Collect reward tokens from the Strategy.\n */\n function collectRewardToken() external;\n\n /**\n * @dev The address of the reward token for the Strategy.\n */\n function rewardTokenAddress() external pure returns (address);\n\n /**\n * @dev The threshold (denominated in the reward token) over which the\n * vault will auto harvest on allocate calls.\n */\n function rewardLiquidationThreshold() external pure returns (uint256);\n}\n" + }, + "contracts/token/OUSD.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Token Contract\n * @dev ERC20 compatible contract for OUSD\n * @dev Implements an elastic supply\n * @author Origin Protocol Inc\n */\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport {\n InitializableERC20Detailed\n} from \"../utils/InitializableERC20Detailed.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\n/**\n * NOTE that this is an ERC20 token but the invariant that the sum of\n * balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the\n * rebasing design. Any integrations with OUSD should be aware.\n */\n\ncontract OUSD is Initializable, InitializableERC20Detailed, Governable {\n using SafeMath for uint256;\n using StableMath for uint256;\n\n event TotalSupplyUpdated(\n uint256 totalSupply,\n uint256 rebasingCredits,\n uint256 rebasingCreditsPerToken\n );\n\n enum RebaseOptions { NotSet, OptOut, OptIn }\n\n uint256 private constant MAX_SUPPLY = ~uint128(0); // (2^128) - 1\n uint256 public _totalSupply;\n mapping(address => mapping(address => uint256)) private _allowances;\n address public vaultAddress = address(0);\n mapping(address => uint256) private _creditBalances;\n uint256 public rebasingCredits;\n uint256 public rebasingCreditsPerToken;\n // Frozen address/credits are non rebasing (value is held in contracts which\n // do not receive yield unless they explicitly opt in)\n uint256 public nonRebasingSupply;\n mapping(address => uint256) public nonRebasingCreditsPerToken;\n mapping(address => RebaseOptions) public rebaseState;\n\n function initialize(\n string calldata _nameArg,\n string calldata _symbolArg,\n address _vaultAddress\n ) external onlyGovernor initializer {\n InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);\n rebasingCreditsPerToken = 1e18;\n vaultAddress = _vaultAddress;\n }\n\n /**\n * @dev Verifies that the caller is the Savings Manager contract\n */\n modifier onlyVault() {\n require(vaultAddress == msg.sender, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @return The total supply of OUSD.\n */\n function totalSupply() public view returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev Gets the balance of the specified address.\n * @param _account Address to query the balance of.\n * @return A uint256 representing the _amount of base units owned by the\n * specified address.\n */\n function balanceOf(address _account) public view returns (uint256) {\n if (_creditBalances[_account] == 0) return 0;\n return\n _creditBalances[_account].divPrecisely(_creditsPerToken(_account));\n }\n\n /**\n * @dev Gets the credits balance of the specified address.\n * @param _account The address to query the balance of.\n * @return (uint256, uint256) Credit balance and credits per token of the\n * address\n */\n function creditsBalanceOf(address _account)\n public\n view\n returns (uint256, uint256)\n {\n return (_creditBalances[_account], _creditsPerToken(_account));\n }\n\n /**\n * @dev Transfer tokens to a specified address.\n * @param _to the address to transfer to.\n * @param _value the _amount to be transferred.\n * @return true on success.\n */\n function transfer(address _to, uint256 _value) public returns (bool) {\n require(_to != address(0), \"Transfer to zero address\");\n require(\n _value <= balanceOf(msg.sender),\n \"Transfer greater than balance\"\n );\n\n _executeTransfer(msg.sender, _to, _value);\n\n emit Transfer(msg.sender, _to, _value);\n\n return true;\n }\n\n /**\n * @dev Transfer tokens from one address to another.\n * @param _from The address you want to send tokens from.\n * @param _to The address you want to transfer to.\n * @param _value The _amount of tokens to be transferred.\n */\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) public returns (bool) {\n require(_to != address(0), \"Transfer to zero address\");\n require(_value <= balanceOf(_from), \"Transfer greater than balance\");\n\n _allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(\n _value\n );\n\n _executeTransfer(_from, _to, _value);\n\n emit Transfer(_from, _to, _value);\n\n return true;\n }\n\n /**\n * @dev Update the count of non rebasing credits in response to a transfer\n * @param _from The address you want to send tokens from.\n * @param _to The address you want to transfer to.\n * @param _value Amount of OUSD to transfer\n */\n function _executeTransfer(\n address _from,\n address _to,\n uint256 _value\n ) internal {\n bool isNonRebasingTo = _isNonRebasingAccount(_to);\n bool isNonRebasingFrom = _isNonRebasingAccount(_from);\n\n // Credits deducted and credited might be different due to the\n // differing creditsPerToken used by each account\n uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));\n uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));\n\n _creditBalances[_from] = _creditBalances[_from].sub(\n creditsDeducted,\n \"Transfer amount exceeds balance\"\n );\n _creditBalances[_to] = _creditBalances[_to].add(creditsCredited);\n\n if (isNonRebasingTo && !isNonRebasingFrom) {\n // Transfer to non-rebasing account from rebasing account, credits\n // are removed from the non rebasing tally\n nonRebasingSupply = nonRebasingSupply.add(_value);\n // Update rebasingCredits by subtracting the deducted amount\n rebasingCredits = rebasingCredits.sub(creditsDeducted);\n } else if (!isNonRebasingTo && isNonRebasingFrom) {\n // Transfer to rebasing account from non-rebasing account\n // Decreasing non-rebasing credits by the amount that was sent\n nonRebasingSupply = nonRebasingSupply.sub(_value);\n // Update rebasingCredits by adding the credited amount\n rebasingCredits = rebasingCredits.add(creditsCredited);\n }\n }\n\n /**\n * @dev Function to check the _amount of tokens that an owner has allowed to a _spender.\n * @param _owner The address which owns the funds.\n * @param _spender The address which will spend the funds.\n * @return The number of tokens still available for the _spender.\n */\n function allowance(address _owner, address _spender)\n public\n view\n returns (uint256)\n {\n return _allowances[_owner][_spender];\n }\n\n /**\n * @dev Approve the passed address to spend the specified _amount of tokens on behalf of\n * msg.sender. This method is included for ERC20 compatibility.\n * increaseAllowance and decreaseAllowance should be used instead.\n * Changing an allowance with this method brings the risk that someone may transfer both\n * the old and the new allowance - if they are both greater than zero - if a transfer\n * transaction is mined before the later approve() call is mined.\n *\n * @param _spender The address which will spend the funds.\n * @param _value The _amount of tokens to be spent.\n */\n function approve(address _spender, uint256 _value) public returns (bool) {\n _allowances[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n /**\n * @dev Increase the _amount of tokens that an owner has allowed to a _spender.\n * This method should be used instead of approve() to avoid the double approval vulnerability\n * described above.\n * @param _spender The address which will spend the funds.\n * @param _addedValue The _amount of tokens to increase the allowance by.\n */\n function increaseAllowance(address _spender, uint256 _addedValue)\n public\n returns (bool)\n {\n _allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]\n .add(_addedValue);\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\n return true;\n }\n\n /**\n * @dev Decrease the _amount of tokens that an owner has allowed to a _spender.\n * @param _spender The address which will spend the funds.\n * @param _subtractedValue The _amount of tokens to decrease the allowance by.\n */\n function decreaseAllowance(address _spender, uint256 _subtractedValue)\n public\n returns (bool)\n {\n uint256 oldValue = _allowances[msg.sender][_spender];\n if (_subtractedValue >= oldValue) {\n _allowances[msg.sender][_spender] = 0;\n } else {\n _allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);\n }\n emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);\n return true;\n }\n\n /**\n * @dev Mints new tokens, increasing totalSupply.\n */\n function mint(address _account, uint256 _amount) external onlyVault {\n _mint(_account, _amount);\n }\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 * - `to` cannot be the zero address.\n */\n function _mint(address _account, uint256 _amount) internal nonReentrant {\n require(_account != address(0), \"Mint to the zero address\");\n\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\n\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\n _creditBalances[_account] = _creditBalances[_account].add(creditAmount);\n\n // If the account is non rebasing and doesn't have a set creditsPerToken\n // then set it i.e. this is a mint from a fresh contract\n if (isNonRebasingAccount) {\n nonRebasingSupply = nonRebasingSupply.add(_amount);\n } else {\n rebasingCredits = rebasingCredits.add(creditAmount);\n }\n\n _totalSupply = _totalSupply.add(_amount);\n\n require(_totalSupply < MAX_SUPPLY, \"Max supply\");\n\n emit Transfer(address(0), _account, _amount);\n }\n\n /**\n * @dev Burns tokens, decreasing totalSupply.\n */\n function burn(address account, uint256 amount) external onlyVault {\n _burn(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 nonReentrant {\n require(_account != address(0), \"Burn from the zero address\");\n if (_amount == 0) {\n return;\n }\n\n bool isNonRebasingAccount = _isNonRebasingAccount(_account);\n uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));\n uint256 currentCredits = _creditBalances[_account];\n\n // Remove the credits, burning rounding errors\n if (\n currentCredits == creditAmount || currentCredits - 1 == creditAmount\n ) {\n // Handle dust from rounding\n _creditBalances[_account] = 0;\n } else if (currentCredits > creditAmount) {\n _creditBalances[_account] = _creditBalances[_account].sub(\n creditAmount\n );\n } else {\n revert(\"Remove exceeds balance\");\n }\n\n // Remove from the credit tallies and non-rebasing supply\n if (isNonRebasingAccount) {\n nonRebasingSupply = nonRebasingSupply.sub(_amount);\n } else {\n rebasingCredits = rebasingCredits.sub(creditAmount);\n }\n\n _totalSupply = _totalSupply.sub(_amount);\n\n emit Transfer(_account, address(0), _amount);\n }\n\n /**\n * @dev Get the credits per token for an account. Returns a fixed amount\n * if the account is non-rebasing.\n * @param _account Address of the account.\n */\n function _creditsPerToken(address _account)\n internal\n view\n returns (uint256)\n {\n if (nonRebasingCreditsPerToken[_account] != 0) {\n return nonRebasingCreditsPerToken[_account];\n } else {\n return rebasingCreditsPerToken;\n }\n }\n\n /**\n * @dev Is an account using rebasing accounting or non-rebasing accounting?\n * Also, ensure contracts are non-rebasing if they have not opted in.\n * @param _account Address of the account.\n */\n function _isNonRebasingAccount(address _account) internal returns (bool) {\n bool isContract = Address.isContract(_account);\n if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {\n _ensureRebasingMigration(_account);\n }\n return nonRebasingCreditsPerToken[_account] > 0;\n }\n\n /**\n * @dev Ensures internal account for rebasing and non-rebasing credits and\n * supply is updated following deployment of frozen yield change.\n */\n function _ensureRebasingMigration(address _account) internal {\n if (nonRebasingCreditsPerToken[_account] == 0) {\n // Set fixed credits per token for this account\n nonRebasingCreditsPerToken[_account] = rebasingCreditsPerToken;\n // Update non rebasing supply\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));\n // Update credit tallies\n rebasingCredits = rebasingCredits.sub(_creditBalances[_account]);\n }\n }\n\n /**\n * @dev Add a contract address to the non rebasing exception list. I.e. the\n * address's balance will be part of rebases so the account will be exposed\n * to upside and downside.\n */\n function rebaseOptIn() public nonReentrant {\n require(_isNonRebasingAccount(msg.sender), \"Account has not opted out\");\n\n // Convert balance into the same amount at the current exchange rate\n uint256 newCreditBalance = _creditBalances[msg.sender]\n .mul(rebasingCreditsPerToken)\n .div(_creditsPerToken(msg.sender));\n\n // Decreasing non rebasing supply\n nonRebasingSupply = nonRebasingSupply.sub(balanceOf(msg.sender));\n\n _creditBalances[msg.sender] = newCreditBalance;\n\n // Increase rebasing credits, totalSupply remains unchanged so no\n // adjustment necessary\n rebasingCredits = rebasingCredits.add(_creditBalances[msg.sender]);\n\n rebaseState[msg.sender] = RebaseOptions.OptIn;\n\n // Delete any fixed credits per token\n delete nonRebasingCreditsPerToken[msg.sender];\n }\n\n /**\n * @dev Remove a contract address to the non rebasing exception list.\n */\n function rebaseOptOut() public nonReentrant {\n require(!_isNonRebasingAccount(msg.sender), \"Account has not opted in\");\n\n // Increase non rebasing supply\n nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));\n // Set fixed credits per token\n nonRebasingCreditsPerToken[msg.sender] = rebasingCreditsPerToken;\n\n // Decrease rebasing credits, total supply remains unchanged so no\n // adjustment necessary\n rebasingCredits = rebasingCredits.sub(_creditBalances[msg.sender]);\n\n // Mark explicitly opted out of rebasing\n rebaseState[msg.sender] = RebaseOptions.OptOut;\n }\n\n /**\n * @dev Modify the supply without minting new tokens. This uses a change in\n * the exchange rate between \"credits\" and OUSD tokens to change balances.\n * @param _newTotalSupply New total supply of OUSD.\n * @return uint256 representing the new total supply.\n */\n function changeSupply(uint256 _newTotalSupply)\n external\n onlyVault\n nonReentrant\n {\n require(_totalSupply > 0, \"Cannot increase 0 supply\");\n\n if (_totalSupply == _newTotalSupply) {\n emit TotalSupplyUpdated(\n _totalSupply,\n rebasingCredits,\n rebasingCreditsPerToken\n );\n return;\n }\n\n _totalSupply = _newTotalSupply > MAX_SUPPLY\n ? MAX_SUPPLY\n : _newTotalSupply;\n\n rebasingCreditsPerToken = rebasingCredits.divPrecisely(\n _totalSupply.sub(nonRebasingSupply)\n );\n\n require(rebasingCreditsPerToken > 0, \"Invalid change in supply\");\n\n _totalSupply = rebasingCredits\n .divPrecisely(rebasingCreditsPerToken)\n .add(nonRebasingSupply);\n\n emit TotalSupplyUpdated(\n _totalSupply,\n rebasingCredits,\n rebasingCreditsPerToken\n );\n }\n}\n" + }, + "contracts/utils/InitializableERC20Detailed.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @dev Optional functions from the ERC20 standard.\n * Converted from openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\n */\ncontract InitializableERC20Detailed is IERC20 {\n // Storage gap to skip storage from prior to OUSD reset\n uint256[100] private _____gap;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\n * these values are immutable: they can only be set once during\n * construction.\n * @notice To avoid variable shadowing appended `Arg` after arguments name.\n */\n function _initialize(\n string memory nameArg,\n string memory symbolArg,\n uint8 decimalsArg\n ) internal {\n _name = nameArg;\n _symbol = symbolArg;\n _decimals = decimalsArg;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view 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 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.\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 returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/vault/VaultAdmin.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Vault Admin Contract\n * @notice The VaultAdmin contract makes configuration and admin calls on the vault.\n * @author Origin Protocol Inc\n */\n\nimport \"./VaultStorage.sol\";\nimport { IOracle } from \"../interfaces/IOracle.sol\";\nimport { IUniswapV2Router } from \"../interfaces/uniswap/IUniswapV2Router02.sol\";\n\ncontract VaultAdmin is VaultStorage {\n /**\n * @dev Verifies that the caller is the Vault, Governor, or Strategist.\n */\n modifier onlyVaultOrGovernorOrStrategist() {\n require(\n msg.sender == address(this) ||\n msg.sender == strategistAddr ||\n isGovernor(),\n \"Caller is not the Vault, Governor, or Strategist\"\n );\n _;\n }\n\n modifier onlyGovernorOrStrategist() {\n require(\n msg.sender == strategistAddr || isGovernor(),\n \"Caller is not the Strategist or Governor\"\n );\n _;\n }\n\n /***************************************\n Configuration\n ****************************************/\n\n /**\n * @dev Set address of price provider.\n * @param _priceProvider Address of price provider\n */\n function setPriceProvider(address _priceProvider) external onlyGovernor {\n priceProvider = _priceProvider;\n emit PriceProviderUpdated(_priceProvider);\n }\n\n /**\n * @dev Set a fee in basis points to be charged for a redeem.\n * @param _redeemFeeBps Basis point fee to be charged\n */\n function setRedeemFeeBps(uint256 _redeemFeeBps) external onlyGovernor {\n redeemFeeBps = _redeemFeeBps;\n emit RedeemFeeUpdated(_redeemFeeBps);\n }\n\n /**\n * @dev Set a buffer of assets to keep in the Vault to handle most\n * redemptions without needing to spend gas unwinding assets from a Strategy.\n * @param _vaultBuffer Percentage using 18 decimals. 100% = 1e18.\n */\n function setVaultBuffer(uint256 _vaultBuffer)\n external\n onlyGovernorOrStrategist\n {\n require(_vaultBuffer <= 1e18, \"Invalid value\");\n vaultBuffer = _vaultBuffer;\n emit VaultBufferUpdated(_vaultBuffer);\n }\n\n /**\n * @dev Sets the minimum amount of OUSD in a mint to trigger an\n * automatic allocation of funds afterwords.\n * @param _threshold OUSD amount with 18 fixed decimals.\n */\n function setAutoAllocateThreshold(uint256 _threshold)\n external\n onlyGovernor\n {\n autoAllocateThreshold = _threshold;\n emit AllocateThresholdUpdated(_threshold);\n }\n\n /**\n * @dev Set a minimum amount of OUSD in a mint or redeem that triggers a\n * rebase\n * @param _threshold OUSD amount with 18 fixed decimals.\n */\n function setRebaseThreshold(uint256 _threshold) external onlyGovernor {\n rebaseThreshold = _threshold;\n emit RebaseThresholdUpdated(_threshold);\n }\n\n /**\n * @dev Set address of Uniswap for performing liquidation of strategy reward\n * tokens\n * @param _address Address of Uniswap\n */\n function setUniswapAddr(address _address) external onlyGovernor {\n uniswapAddr = _address;\n emit UniswapUpdated(_address);\n }\n\n /**\n * @dev Set address of Strategist\n * @param _address Address of Strategist\n */\n function setStrategistAddr(address _address) external onlyGovernor {\n strategistAddr = _address;\n emit StrategistUpdated(_address);\n }\n\n /**\n * @dev Set the default Strategy for an asset, i.e. the one which the asset\n will be automatically allocated to and withdrawn from\n * @param _asset Address of the asset\n * @param _strategy Address of the Strategy\n */\n function setAssetDefaultStrategy(address _asset, address _strategy)\n external\n onlyGovernorOrStrategist\n {\n emit AssetDefaultStrategyUpdated(_asset, _strategy);\n require(strategies[_strategy].isSupported, \"Strategy not approved\");\n IStrategy strategy = IStrategy(_strategy);\n require(assets[_asset].isSupported, \"Asset is not supported\");\n require(\n strategy.supportsAsset(_asset),\n \"Asset not supported by Strategy\"\n );\n assetDefaultStrategies[_asset] = _strategy;\n }\n\n /**\n * @dev Add a supported asset to the contract, i.e. one that can be\n * to mint OUSD.\n * @param _asset Address of asset\n */\n function supportAsset(address _asset) external onlyGovernor {\n require(!assets[_asset].isSupported, \"Asset already supported\");\n\n assets[_asset] = Asset({ isSupported: true });\n allAssets.push(_asset);\n\n // Verify that our oracle supports the asset\n // slither-disable-next-line unused-return\n IOracle(priceProvider).price(_asset);\n\n emit AssetSupported(_asset);\n }\n\n /**\n * @dev Add a strategy to the Vault.\n * @param _addr Address of the strategy to add\n */\n function approveStrategy(address _addr) external onlyGovernor {\n require(!strategies[_addr].isSupported, \"Strategy already approved\");\n strategies[_addr] = Strategy({ isSupported: true, _deprecated: 0 });\n allStrategies.push(_addr);\n emit StrategyApproved(_addr);\n }\n\n /**\n * @dev Remove a strategy from the Vault. Removes all invested assets and\n * returns them to the Vault.\n * @param _addr Address of the strategy to remove\n */\n\n function removeStrategy(address _addr) external onlyGovernor {\n require(strategies[_addr].isSupported, \"Strategy not approved\");\n\n // Initialize strategyIndex with out of bounds result so function will\n // revert if no valid index found\n uint256 strategyIndex = allStrategies.length;\n for (uint256 i = 0; i < allStrategies.length; i++) {\n if (allStrategies[i] == _addr) {\n strategyIndex = i;\n break;\n }\n }\n\n if (strategyIndex < allStrategies.length) {\n allStrategies[strategyIndex] = allStrategies[allStrategies.length -\n 1];\n allStrategies.pop();\n\n // Withdraw all assets\n IStrategy strategy = IStrategy(_addr);\n strategy.withdrawAll();\n // Call harvest after withdraw in case withdraw triggers\n // distribution of additional reward tokens (true for Compound)\n _harvest(_addr);\n emit StrategyRemoved(_addr);\n }\n\n // Clean up struct in mapping, this can be removed later\n // See https://github.com/OriginProtocol/origin-dollar/issues/324\n strategies[_addr].isSupported = false;\n }\n\n /**\n * @notice Move assets from one Strategy to another\n * @param _strategyFromAddress Address of Strategy to move assets from.\n * @param _strategyToAddress Address of Strategy to move assets to.\n * @param _assets Array of asset address that will be moved\n * @param _amounts Array of amounts of each corresponding asset to move.\n */\n function reallocate(\n address _strategyFromAddress,\n address _strategyToAddress,\n address[] calldata _assets,\n uint256[] calldata _amounts\n ) external onlyGovernorOrStrategist {\n require(\n strategies[_strategyFromAddress].isSupported,\n \"Invalid from Strategy\"\n );\n require(\n strategies[_strategyToAddress].isSupported,\n \"Invalid to Strategy\"\n );\n require(_assets.length == _amounts.length, \"Parameter length mismatch\");\n\n IStrategy strategyFrom = IStrategy(_strategyFromAddress);\n IStrategy strategyTo = IStrategy(_strategyToAddress);\n\n for (uint256 i = 0; i < _assets.length; i++) {\n require(strategyTo.supportsAsset(_assets[i]), \"Asset unsupported\");\n // Withdraw from Strategy and pass other Strategy as recipient\n strategyFrom.withdraw(address(strategyTo), _assets[i], _amounts[i]);\n }\n // Tell new Strategy to deposit into protocol\n strategyTo.depositAll();\n }\n\n /**\n * @dev Sets the maximum allowable difference between\n * total supply and backing assets' value.\n */\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor {\n maxSupplyDiff = _maxSupplyDiff;\n emit MaxSupplyDiffChanged(_maxSupplyDiff);\n }\n\n /**\n * @dev Sets the trusteeAddress that can receive a portion of yield.\n * Setting to the zero address disables this feature.\n */\n function setTrusteeAddress(address _address) external onlyGovernor {\n trusteeAddress = _address;\n emit TrusteeAddressChanged(_address);\n }\n\n /**\n * @dev Sets the TrusteeFeeBps to the percentage of yield that should be\n * received in basis points.\n */\n function setTrusteeFeeBps(uint256 _basis) external onlyGovernor {\n require(_basis <= 5000, \"basis cannot exceed 50%\");\n trusteeFeeBps = _basis;\n emit TrusteeFeeBpsChanged(_basis);\n }\n\n /***************************************\n Pause\n ****************************************/\n\n /**\n * @dev Set the deposit paused flag to true to prevent rebasing.\n */\n function pauseRebase() external onlyGovernorOrStrategist {\n rebasePaused = true;\n emit RebasePaused();\n }\n\n /**\n * @dev Set the deposit paused flag to true to allow rebasing.\n */\n function unpauseRebase() external onlyGovernor {\n rebasePaused = false;\n emit RebaseUnpaused();\n }\n\n /**\n * @dev Set the deposit paused flag to true to prevent capital movement.\n */\n function pauseCapital() external onlyGovernorOrStrategist {\n capitalPaused = true;\n emit CapitalPaused();\n }\n\n /**\n * @dev Set the deposit paused flag to false to enable capital movement.\n */\n function unpauseCapital() external onlyGovernorOrStrategist {\n capitalPaused = false;\n emit CapitalUnpaused();\n }\n\n /***************************************\n Rewards\n ****************************************/\n\n /**\n * @dev Transfer token to governor. Intended for recovering tokens stuck in\n * contract, i.e. mistaken sends.\n * @param _asset Address for the asset\n * @param _amount Amount of the asset to transfer\n */\n function transferToken(address _asset, uint256 _amount)\n external\n onlyGovernor\n {\n require(!assets[_asset].isSupported, \"Only unsupported assets\");\n IERC20(_asset).safeTransfer(governor(), _amount);\n }\n\n /**\n * @dev Collect reward tokens from all strategies and swap for supported\n * stablecoin via Uniswap\n */\n function harvest() external onlyGovernorOrStrategist {\n for (uint256 i = 0; i < allStrategies.length; i++) {\n _harvest(allStrategies[i]);\n }\n }\n\n /**\n * @dev Collect reward tokens for a specific strategy and swap for supported\n * stablecoin via Uniswap. Called from the vault.\n * @param _strategyAddr Address of the strategy to collect rewards from\n */\n function harvest(address _strategyAddr)\n external\n onlyVaultOrGovernorOrStrategist\n returns (uint256[] memory)\n {\n return _harvest(_strategyAddr);\n }\n\n /**\n * @dev Collect reward tokens from a single strategy and swap them for a\n * supported stablecoin via Uniswap\n * @param _strategyAddr Address of the strategy to collect rewards from\n */\n function _harvest(address _strategyAddr)\n internal\n returns (uint256[] memory)\n {\n IStrategy strategy = IStrategy(_strategyAddr);\n address rewardTokenAddress = strategy.rewardTokenAddress();\n if (rewardTokenAddress != address(0)) {\n strategy.collectRewardToken();\n\n if (uniswapAddr != address(0)) {\n IERC20 rewardToken = IERC20(strategy.rewardTokenAddress());\n uint256 rewardTokenAmount = rewardToken.balanceOf(\n address(this)\n );\n if (rewardTokenAmount > 0) {\n // Give Uniswap full amount allowance\n rewardToken.safeApprove(uniswapAddr, 0);\n rewardToken.safeApprove(uniswapAddr, rewardTokenAmount);\n\n // Uniswap redemption path\n address[] memory path = new address[](3);\n path[0] = strategy.rewardTokenAddress();\n path[1] = IUniswapV2Router(uniswapAddr).WETH();\n path[2] = allAssets[1]; // USDT\n\n return\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\n rewardTokenAmount,\n uint256(0),\n path,\n address(this),\n now.add(1800)\n );\n }\n }\n }\n }\n\n /***************************************\n Pricing\n ****************************************/\n\n /**\n * @dev Returns the total price in 18 digit USD for a given asset.\n * Never goes above 1, since that is how we price mints\n * @param asset address of the asset\n * @return uint256 USD price of 1 of the asset, in 18 decimal fixed\n */\n function priceUSDMint(address asset) external view returns (uint256) {\n uint256 price = IOracle(priceProvider).price(asset);\n if (price > 1e8) {\n price = 1e8;\n }\n // Price from Oracle is returned with 8 decimals\n // scale to 18 so 18-8=10\n return price.scaleBy(10);\n }\n\n /**\n * @dev Returns the total price in 18 digit USD for a given asset.\n * Never goes below 1, since that is how we price redeems\n * @param asset Addresss of the asset\n * @return uint256 USD price of 1 of the asset, in 18 decimal fixed\n */\n function priceUSDRedeem(address asset) external view returns (uint256) {\n uint256 price = IOracle(priceProvider).price(asset);\n if (price < 1e8) {\n price = 1e8;\n }\n // Price from Oracle is returned with 8 decimals\n // scale to 18 so 18-8=10\n return price.scaleBy(10);\n }\n\n /***************************************\n Strategies Admin\n ****************************************/\n\n /**\n * @dev Withdraws all assets from the strategy and sends assets to the Vault.\n * @param _strategyAddr Strategy address.\n */\n function withdrawAllFromStrategy(address _strategyAddr)\n external\n onlyGovernorOrStrategist\n {\n require(\n strategies[_strategyAddr].isSupported,\n \"Strategy is not supported\"\n );\n IStrategy strategy = IStrategy(_strategyAddr);\n strategy.withdrawAll();\n }\n\n /**\n * @dev Withdraws all assets from all the strategies and sends assets to the Vault.\n */\n function withdrawAllFromStrategies() external onlyGovernorOrStrategist {\n for (uint256 i = 0; i < allStrategies.length; i++) {\n IStrategy strategy = IStrategy(allStrategies[i]);\n strategy.withdrawAll();\n }\n }\n}\n" + }, + "contracts/interfaces/IOracle.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IOracle {\n /**\n * @dev returns the asset price in USD, 8 decimal digits.\n */\n function price(address asset) external view returns (uint256);\n}\n" + }, + "contracts/mocks/MockUniswapRouter.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IUniswapV2Router } from \"../interfaces/uniswap/IUniswapV2Router02.sol\";\nimport { Helpers } from \"../utils/Helpers.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\n\ncontract MockUniswapRouter is IUniswapV2Router {\n using StableMath for uint256;\n\n address tok0;\n address tok1;\n\n address public WETH = address(0);\n\n function initialize(address _token0, address _token1) public {\n tok0 = _token0;\n tok1 = _token1;\n }\n\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts) {\n IERC20(tok0).transferFrom(msg.sender, address(this), amountIn);\n IERC20(tok1).transfer(\n to,\n amountIn.scaleBy(\n int8(Helpers.getDecimals(tok1) - Helpers.getDecimals(tok0))\n )\n );\n }\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint256 amountADesired,\n uint256 amountBDesired,\n uint256 amountAMin,\n uint256 amountBMin,\n address to,\n uint256 deadline\n )\n external\n returns (\n uint256 amountA,\n uint256 amountB,\n uint256 liquidity\n )\n {\n // this is needed to make this contract whole else it'd be just virtual\n }\n}\n" + }, + "contracts/staking/SingleAssetStaking.sol": { + "content": "pragma solidity 0.5.11;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\n\ncontract SingleAssetStaking is Initializable, Governable {\n using SafeMath for uint256;\n using StableMath for uint256;\n using SafeERC20 for IERC20;\n\n /* ========== STATE VARIABLES ========== */\n\n IERC20 public stakingToken; // this is both the staking and rewards\n\n struct Stake {\n uint256 amount; // amount to stake\n uint256 end; // when does the staking period end\n uint256 duration; // the duration of the stake\n uint240 rate; // rate to charge use 248 to reserve 8 bits for the bool\n bool paid;\n uint8 stakeType;\n }\n\n struct DropRoot {\n bytes32 hash;\n uint256 depth;\n }\n\n uint256[] public durations; // allowed durations\n uint256[] public rates; // rates that correspond with the allowed durations\n\n uint256 public totalOutstanding;\n bool public paused;\n\n mapping(address => Stake[]) public userStakes;\n\n mapping(uint8 => DropRoot) public dropRoots;\n\n // type 0 is reserved for stakes done by the user, all other types will be drop/preApproved stakes\n uint8 constant USER_STAKE_TYPE = 0;\n uint256 constant MAX_STAKES = 256;\n\n /* ========== Initialize ========== */\n\n /**\n * @dev Initialize the contracts, sets up durations, rates, and preApprover\n * for preApproved contracts can only be called once\n * @param _stakingToken Address of the token that we are staking\n * @param _durations Array of allowed durations in seconds\n * @param _rates Array of rates(0.3 is 30%) that correspond to the allowed\n * durations in 1e18 precision\n */\n function initialize(\n address _stakingToken,\n uint256[] calldata _durations,\n uint256[] calldata _rates\n ) external onlyGovernor initializer {\n stakingToken = IERC20(_stakingToken);\n _setDurationRates(_durations, _rates);\n }\n\n /* ========= Internal helper functions ======== */\n\n /**\n * @dev Validate and set the duration and corresponding rates, will emit\n * events NewRate and NewDurations\n */\n function _setDurationRates(\n uint256[] memory _durations,\n uint256[] memory _rates\n ) internal {\n require(\n _rates.length == _durations.length,\n \"Mismatch durations and rates\"\n );\n\n for (uint256 i = 0; i < _rates.length; i++) {\n require(_rates[i] < uint240(-1), \"Max rate exceeded\");\n }\n\n rates = _rates;\n durations = _durations;\n\n emit NewRates(msg.sender, rates);\n emit NewDurations(msg.sender, durations);\n }\n\n function _totalExpectedRewards(Stake[] storage stakes)\n internal\n view\n returns (uint256 total)\n {\n for (uint256 i = 0; i < stakes.length; i++) {\n Stake storage stake = stakes[i];\n if (!stake.paid) {\n total = total.add(stake.amount.mulTruncate(stake.rate));\n }\n }\n }\n\n function _totalExpected(Stake storage _stake)\n internal\n view\n returns (uint256)\n {\n return _stake.amount.add(_stake.amount.mulTruncate(_stake.rate));\n }\n\n function _airDroppedStakeClaimed(address account, uint8 stakeType)\n internal\n view\n returns (bool)\n {\n Stake[] storage stakes = userStakes[account];\n for (uint256 i = 0; i < stakes.length; i++) {\n if (stakes[i].stakeType == stakeType) {\n return true;\n }\n }\n return false;\n }\n\n function _findDurationRate(uint256 duration)\n internal\n view\n returns (uint240)\n {\n for (uint256 i = 0; i < durations.length; i++) {\n if (duration == durations[i]) {\n return uint240(rates[i]);\n }\n }\n return 0;\n }\n\n /**\n * @dev Internal staking function\n * will insert the stake into the stakes array and verify we have\n * enough to pay off stake + reward\n * @param staker Address of the staker\n * @param stakeType Number that represent the type of the stake, 0 is user\n * initiated all else is currently preApproved\n * @param duration Number of seconds this stake will be held for\n * @param rate Rate(0.3 is 30%) of reward for this stake in 1e18, uint240 =\n * to fit the bool and type in struct Stake\n * @param amount Number of tokens to stake in 1e18\n */\n function _stake(\n address staker,\n uint8 stakeType,\n uint256 duration,\n uint240 rate,\n uint256 amount\n ) internal {\n require(!paused, \"Staking paused\");\n\n Stake[] storage stakes = userStakes[staker];\n\n uint256 end = block.timestamp.add(duration);\n\n uint256 i = stakes.length; // start at the end of the current array\n\n require(i < MAX_STAKES, \"Max stakes\");\n\n stakes.length += 1; // grow the array\n // find the spot where we can insert the current stake\n // this should make an increasing list sorted by end\n while (i != 0 && stakes[i - 1].end > end) {\n // shift it back one\n stakes[i] = stakes[i - 1];\n i -= 1;\n }\n\n // insert the stake\n Stake storage newStake = stakes[i];\n newStake.rate = rate;\n newStake.stakeType = stakeType;\n newStake.end = end;\n newStake.duration = duration;\n newStake.amount = amount;\n\n totalOutstanding = totalOutstanding.add(_totalExpected(newStake));\n\n emit Staked(staker, amount, duration, rate);\n }\n\n function _stakeWithChecks(\n address staker,\n uint256 amount,\n uint256 duration\n ) internal {\n require(amount > 0, \"Cannot stake 0\");\n\n uint240 rewardRate = _findDurationRate(duration);\n require(rewardRate > 0, \"Invalid duration\"); // we couldn't find the rate that correspond to the passed duration\n\n _stake(staker, USER_STAKE_TYPE, duration, rewardRate, amount);\n // transfer in the token so that we can stake the correct amount\n stakingToken.safeTransferFrom(staker, address(this), amount);\n }\n\n modifier requireLiquidity() {\n // we need to have enough balance to cover the rewards after the operation is complete\n _;\n require(\n stakingToken.balanceOf(address(this)) >= totalOutstanding,\n \"Insufficient rewards\"\n );\n }\n\n /* ========== VIEWS ========== */\n\n function getAllDurations() external view returns (uint256[] memory) {\n return durations;\n }\n\n function getAllRates() external view returns (uint256[] memory) {\n return rates;\n }\n\n /**\n * @dev Return all the stakes paid and unpaid for a given user\n * @param account Address of the account that we want to look up\n */\n function getAllStakes(address account)\n external\n view\n returns (Stake[] memory)\n {\n return userStakes[account];\n }\n\n /**\n * @dev Find the rate that corresponds to a given duration\n * @param _duration Number of seconds\n */\n function durationRewardRate(uint256 _duration)\n external\n view\n returns (uint256)\n {\n return _findDurationRate(_duration);\n }\n\n /**\n * @dev Has the airdropped stake already been claimed\n */\n function airDroppedStakeClaimed(address account, uint8 stakeType)\n external\n view\n returns (bool)\n {\n return _airDroppedStakeClaimed(account, stakeType);\n }\n\n /**\n * @dev Calculate all the staked value a user has put into the contract,\n * rewards not included\n * @param account Address of the account that we want to look up\n */\n function totalStaked(address account)\n external\n view\n returns (uint256 total)\n {\n Stake[] storage stakes = userStakes[account];\n\n for (uint256 i = 0; i < stakes.length; i++) {\n if (!stakes[i].paid) {\n total = total.add(stakes[i].amount);\n }\n }\n }\n\n /**\n * @dev Calculate all the rewards a user can expect to receive.\n * @param account Address of the account that we want to look up\n */\n function totalExpectedRewards(address account)\n external\n view\n returns (uint256)\n {\n return _totalExpectedRewards(userStakes[account]);\n }\n\n /**\n * @dev Calculate all current holdings of a user: staked value + prorated rewards\n * @param account Address of the account that we want to look up\n */\n function totalCurrentHoldings(address account)\n external\n view\n returns (uint256 total)\n {\n Stake[] storage stakes = userStakes[account];\n\n for (uint256 i = 0; i < stakes.length; i++) {\n Stake storage stake = stakes[i];\n if (stake.paid) {\n continue;\n } else if (stake.end < block.timestamp) {\n total = total.add(_totalExpected(stake));\n } else {\n //calcualte the precentage accrued in term of rewards\n total = total.add(\n stake.amount.add(\n stake.amount.mulTruncate(stake.rate).mulTruncate(\n stake\n .duration\n .sub(stake.end.sub(block.timestamp))\n .divPrecisely(stake.duration)\n )\n )\n );\n }\n }\n }\n\n /* ========== MUTATIVE FUNCTIONS ========== */\n\n /**\n * @dev Make a preapproved stake for the user, this is a presigned voucher that the user can redeem either from\n * an airdrop or a compensation program.\n * Only 1 of each type is allowed per user. The proof must match the root hash\n * @param index Number that is zero base index of the stake in the payout entry\n * @param stakeType Number that represent the type of the stake, must not be 0 which is user stake\n * @param duration Number of seconds this stake will be held for\n * @param rate Rate(0.3 is 30%) of reward for this stake in 1e18, uint240 to fit the bool and type in struct Stake\n * @param amount Number of tokens to stake in 1e18\n * @param merkleProof Array of proofs for that amount\n */\n function airDroppedStake(\n uint256 index,\n uint8 stakeType,\n uint256 duration,\n uint256 rate,\n uint256 amount,\n bytes32[] calldata merkleProof\n ) external requireLiquidity {\n require(stakeType != USER_STAKE_TYPE, \"Cannot be normal staking\");\n require(rate < uint240(-1), \"Max rate exceeded\");\n require(index < 2**merkleProof.length, \"Invalid index\");\n DropRoot storage dropRoot = dropRoots[stakeType];\n require(merkleProof.length == dropRoot.depth, \"Invalid proof\");\n\n // Compute the merkle root\n bytes32 node = keccak256(\n abi.encodePacked(\n index,\n stakeType,\n address(this),\n msg.sender,\n duration,\n rate,\n amount\n )\n );\n uint256 path = index;\n for (uint16 i = 0; i < merkleProof.length; i++) {\n if ((path & 0x01) == 1) {\n node = keccak256(abi.encodePacked(merkleProof[i], node));\n } else {\n node = keccak256(abi.encodePacked(node, merkleProof[i]));\n }\n path /= 2;\n }\n\n // Check the merkle proof\n require(node == dropRoot.hash, \"Stake not approved\");\n\n // verify that we haven't already staked\n require(\n !_airDroppedStakeClaimed(msg.sender, stakeType),\n \"Already staked\"\n );\n\n _stake(msg.sender, stakeType, duration, uint240(rate), amount);\n }\n\n /**\n * @dev Stake an approved amount of staking token into the contract.\n * User must have already approved the contract for specified amount.\n * @param amount Number of tokens to stake in 1e18\n * @param duration Number of seconds this stake will be held for\n */\n function stake(uint256 amount, uint256 duration) external requireLiquidity {\n // no checks are performed in this function since those are already present in _stakeWithChecks\n _stakeWithChecks(msg.sender, amount, duration);\n }\n\n /**\n * @dev Stake an approved amount of staking token into the contract. This function\n * can only be called by OGN token contract.\n * @param staker Address of the account that is creating the stake\n * @param amount Number of tokens to stake in 1e18\n * @param duration Number of seconds this stake will be held for\n */\n function stakeWithSender(\n address staker,\n uint256 amount,\n uint256 duration\n ) external returns (bool) {\n require(\n msg.sender == address(stakingToken),\n \"Only token contract can make this call\"\n );\n\n _stakeWithChecks(staker, amount, duration);\n return true;\n }\n\n /**\n * @dev Exit out of all possible stakes\n */\n function exit() external requireLiquidity {\n Stake[] storage stakes = userStakes[msg.sender];\n require(stakes.length > 0, \"Nothing staked\");\n\n uint256 totalWithdraw = 0;\n uint256 stakedAmount = 0;\n uint256 l = stakes.length;\n do {\n Stake storage exitStake = stakes[l - 1];\n // stop on the first ended stake that's already been paid\n if (exitStake.end < block.timestamp && exitStake.paid) {\n break;\n }\n //might not be ended\n if (exitStake.end < block.timestamp) {\n //we are paying out the stake\n exitStake.paid = true;\n totalWithdraw = totalWithdraw.add(_totalExpected(exitStake));\n stakedAmount = stakedAmount.add(exitStake.amount);\n }\n l--;\n } while (l > 0);\n require(totalWithdraw > 0, \"All stakes in lock-up\");\n\n totalOutstanding = totalOutstanding.sub(totalWithdraw);\n emit Withdrawn(msg.sender, totalWithdraw, stakedAmount);\n stakingToken.safeTransfer(msg.sender, totalWithdraw);\n }\n\n /* ========== MODIFIERS ========== */\n\n function setPaused(bool _paused) external onlyGovernor {\n paused = _paused;\n emit Paused(msg.sender, paused);\n }\n\n /**\n * @dev Set new durations and rates will not effect existing stakes\n * @param _durations Array of durations in seconds\n * @param _rates Array of rates that corresponds to the durations (0.01 is 1%) in 1e18\n */\n function setDurationRates(\n uint256[] calldata _durations,\n uint256[] calldata _rates\n ) external onlyGovernor {\n _setDurationRates(_durations, _rates);\n }\n\n /**\n * @dev Set air drop root for a specific stake type\n * @param _stakeType Type of staking must be greater than 0\n * @param _rootHash Root hash of the Merkle Tree\n * @param _proofDepth Depth of the Merklke Tree\n */\n function setAirDropRoot(\n uint8 _stakeType,\n bytes32 _rootHash,\n uint256 _proofDepth\n ) external onlyGovernor {\n require(_stakeType != USER_STAKE_TYPE, \"Cannot be normal staking\");\n dropRoots[_stakeType].hash = _rootHash;\n dropRoots[_stakeType].depth = _proofDepth;\n emit NewAirDropRootHash(_stakeType, _rootHash, _proofDepth);\n }\n\n /* ========== EVENTS ========== */\n\n event Staked(\n address indexed user,\n uint256 amount,\n uint256 duration,\n uint256 rate\n );\n event Withdrawn(address indexed user, uint256 amount, uint256 stakedAmount);\n event Paused(address indexed user, bool yes);\n event NewDurations(address indexed user, uint256[] durations);\n event NewRates(address indexed user, uint256[] rates);\n event NewAirDropRootHash(\n uint8 stakeType,\n bytes32 rootHash,\n uint256 proofDepth\n );\n}\n" + }, + "contracts/proxies/InitializeGovernedUpgradeabilityProxy.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { Governable } from \"../governance/Governable.sol\";\nimport {\n BaseUpgradeabilityProxy\n} from \"@openzeppelin/upgrades/contracts/upgradeability/BaseUpgradeabilityProxy.sol\";\n\n/**\n * @title BaseGovernedUpgradeabilityProxy\n * @dev This contract combines an upgradeability proxy with our governor system\n * @author Origin Protocol Inc\n */\ncontract InitializeGovernedUpgradeabilityProxy is\n Governable,\n BaseUpgradeabilityProxy\n{\n /**\n * @dev Contract initializer with Governor enforcement\n * @param _logic Address of the initial implementation.\n * @param _initGovernor Address of the initial Governor.\n * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.\n * It should include the signature and the parameters of the function to be called, as described in\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\n * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\n */\n function initialize(\n address _logic,\n address _initGovernor,\n bytes memory _data\n ) public payable onlyGovernor {\n require(_implementation() == address(0));\n assert(\n IMPLEMENTATION_SLOT ==\n bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1)\n );\n _changeGovernor(_initGovernor);\n _setImplementation(_logic);\n if (_data.length > 0) {\n (bool success, ) = _logic.delegatecall(_data);\n require(success);\n }\n }\n\n /**\n * @return The address of the proxy admin/it's also the governor.\n */\n function admin() external view returns (address) {\n return _governor();\n }\n\n /**\n * @return The address of the implementation.\n */\n function implementation() external view returns (address) {\n return _implementation();\n }\n\n /**\n * @dev Upgrade the backing implementation of the proxy.\n * Only the admin can call this function.\n * @param newImplementation Address of the new implementation.\n */\n function upgradeTo(address newImplementation) external onlyGovernor {\n _upgradeTo(newImplementation);\n }\n\n /**\n * @dev Upgrade the backing implementation of the proxy and call a function\n * on the new implementation.\n * This is useful to initialize the proxied contract.\n * @param newImplementation Address of the new implementation.\n * @param data Data to send as msg.data in the low level call.\n * It should include the signature and the parameters of the function to be called, as described in\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data)\n external\n payable\n onlyGovernor\n {\n _upgradeTo(newImplementation);\n (bool success, ) = newImplementation.delegatecall(data);\n require(success);\n }\n}\n" + }, + "@openzeppelin/upgrades/contracts/upgradeability/BaseUpgradeabilityProxy.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport './Proxy.sol';\nimport '../utils/Address.sol';\n\n/**\n * @title BaseUpgradeabilityProxy\n * @dev This contract implements a proxy that allows to change the\n * implementation address to which it will delegate.\n * Such a change is called an implementation upgrade.\n */\ncontract BaseUpgradeabilityProxy is Proxy {\n /**\n * @dev Emitted when the implementation is upgraded.\n * @param implementation Address of the new implementation.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation.\n * @return Address of the current implementation\n */\n function _implementation() internal view returns (address impl) {\n bytes32 slot = IMPLEMENTATION_SLOT;\n assembly {\n impl := sload(slot)\n }\n }\n\n /**\n * @dev Upgrades the proxy to a new implementation.\n * @param newImplementation Address of the new implementation.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation address of the proxy.\n * @param newImplementation Address of the new implementation.\n */\n function _setImplementation(address newImplementation) internal {\n require(OpenZeppelinUpgradesAddress.isContract(newImplementation), \"Cannot set a proxy implementation to a non-contract address\");\n\n bytes32 slot = IMPLEMENTATION_SLOT;\n\n assembly {\n sstore(slot, newImplementation)\n }\n }\n}\n" + }, + "@openzeppelin/upgrades/contracts/upgradeability/Proxy.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @title Proxy\n * @dev Implements delegation of calls to other contracts, with proper\n * forwarding of return values and bubbling of failures.\n * It defines a fallback function that delegates all calls to the address\n * returned by the abstract _implementation() internal function.\n */\ncontract Proxy {\n /**\n * @dev Fallback function.\n * Implemented entirely in `_fallback`.\n */\n function () payable external {\n _fallback();\n }\n\n /**\n * @return The Address of the implementation.\n */\n function _implementation() internal view returns (address);\n\n /**\n * @dev Delegates execution to an implementation contract.\n * This is a low level function that doesn't return to its internal call site.\n * It will return to the external caller whatever the implementation returns.\n * @param implementation Address to delegate.\n */\n function _delegate(address implementation) internal {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize)\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize)\n\n switch result\n // delegatecall returns 0 on error.\n case 0 { revert(0, returndatasize) }\n default { return(0, returndatasize) }\n }\n }\n\n /**\n * @dev Function that is run as the first thing in the fallback function.\n * Can be redefined in derived contracts to add functionality.\n * Redefinitions must call super._willFallback().\n */\n function _willFallback() internal {\n }\n\n /**\n * @dev fallback implementation.\n * Extracted to enable manual triggering.\n */\n function _fallback() internal {\n _willFallback();\n _delegate(_implementation());\n }\n}\n" + }, + "@openzeppelin/upgrades/contracts/utils/Address.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * Utility library of inline functions on addresses\n *\n * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/utils/Address.sol\n * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts\n * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the\n * build/artifacts folder) as well as the vanilla Address implementation from an openzeppelin version.\n */\nlibrary OpenZeppelinUpgradesAddress {\n /**\n * Returns whether the target address is a contract\n * @dev This function will return false if invoked during the constructor of a contract,\n * as the code is not actually created until after the constructor finishes.\n * @param account address of the account to check\n * @return whether the target address is a contract\n */\n function isContract(address account) internal view returns (bool) {\n uint256 size;\n // XXX Currently there is no better way to check if there is a contract in an address\n // than to check the size of the code at that address.\n // See https://ethereum.stackexchange.com/a/14016/36603\n // for more details about how this works.\n // TODO Check this again before the Serenity release, because all addresses will be\n // contracts then.\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n}\n" + }, + "contracts/proxies/Proxies.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n InitializeGovernedUpgradeabilityProxy\n} from \"./InitializeGovernedUpgradeabilityProxy.sol\";\n\n/**\n * @notice OUSDProxy delegates calls to an OUSD implementation\n */\ncontract OUSDProxy is InitializeGovernedUpgradeabilityProxy {\n\n}\n\n/**\n * @notice VaultProxy delegates calls to a Vault implementation\n */\ncontract VaultProxy is InitializeGovernedUpgradeabilityProxy {\n\n}\n\n/**\n * @notice CompoundStrategyProxy delegates calls to a CompoundStrategy implementation\n */\ncontract CompoundStrategyProxy is InitializeGovernedUpgradeabilityProxy {\n\n}\n\n/**\n * @notice ThreePoolStrategyProxy delegates calls to a ThreePoolStrategy implementation\n */\ncontract ThreePoolStrategyProxy is InitializeGovernedUpgradeabilityProxy {\n\n}\n" + }, + "contracts/oracle/MixOracle.sol": { + "content": "// DEPRECATED - This contract is no longer used in production\n\npragma solidity 0.5.11;\n\n/**\n * @title OUSD MixOracle Contract\n * @notice The MixOracle pulls exchange rate from multiple oracles and returns\n * min and max values.\n * @author Origin Protocol Inc\n */\nimport { IPriceOracle } from \"../interfaces/IPriceOracle.sol\";\nimport { IEthUsdOracle } from \"../interfaces/IEthUsdOracle.sol\";\nimport { IMinMaxOracle } from \"../interfaces/IMinMaxOracle.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\ncontract MixOracle is IMinMaxOracle, Governable {\n event DriftsUpdated(uint256 _minDrift, uint256 _maxDrift);\n event EthUsdOracleRegistered(address _oracle);\n event EthUsdOracleDeregistered(address _oracle);\n event TokenOracleRegistered(\n string symbol,\n address[] ethOracles,\n address[] usdOracles\n );\n\n address[] public ethUsdOracles;\n\n struct MixConfig {\n address[] usdOracles;\n address[] ethOracles;\n }\n\n mapping(bytes32 => MixConfig) configs;\n\n uint256 constant MAX_INT = 2**256 - 1;\n uint256 public maxDrift;\n uint256 public minDrift;\n\n constructor(uint256 _maxDrift, uint256 _minDrift) public {\n maxDrift = _maxDrift;\n minDrift = _minDrift;\n emit DriftsUpdated(_minDrift, _maxDrift);\n }\n\n function setMinMaxDrift(uint256 _minDrift, uint256 _maxDrift)\n public\n onlyGovernor\n {\n minDrift = _minDrift;\n maxDrift = _maxDrift;\n emit DriftsUpdated(_minDrift, _maxDrift);\n }\n\n /**\n * @notice Adds an oracle to the list of oracles to pull data from.\n * @param oracle Address of an oracle that implements the IEthUsdOracle interface.\n **/\n function registerEthUsdOracle(address oracle) public onlyGovernor {\n for (uint256 i = 0; i < ethUsdOracles.length; i++) {\n require(ethUsdOracles[i] != oracle, \"Oracle already registered.\");\n }\n ethUsdOracles.push(oracle);\n emit EthUsdOracleRegistered(oracle);\n }\n\n /**\n * @notice Removes an oracle to the list of oracles to pull data from.\n * @param oracle Address of an oracle that implements the IEthUsdOracle interface.\n **/\n function unregisterEthUsdOracle(address oracle) public onlyGovernor {\n for (uint256 i = 0; i < ethUsdOracles.length; i++) {\n if (ethUsdOracles[i] == oracle) {\n // swap with the last element of the array, and then delete last element (could be itself)\n ethUsdOracles[i] = ethUsdOracles[ethUsdOracles.length - 1];\n delete ethUsdOracles[ethUsdOracles.length - 1];\n emit EthUsdOracleDeregistered(oracle);\n ethUsdOracles.pop();\n return;\n }\n }\n revert(\"Oracle not found\");\n }\n\n /**\n * @notice Adds an oracle to the list of oracles to pull data from.\n * @param ethOracles Addresses of oracles that implements the IEthUsdOracle interface and answers for this asset\n * @param usdOracles Addresses of oracles that implements the IPriceOracle interface and answers for this asset\n **/\n function registerTokenOracles(\n string calldata symbol,\n address[] calldata ethOracles,\n address[] calldata usdOracles\n ) external onlyGovernor {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n config.ethOracles = ethOracles;\n config.usdOracles = usdOracles;\n emit TokenOracleRegistered(symbol, ethOracles, usdOracles);\n }\n\n /**\n * @notice Returns the min price of an asset in USD.\n * @return symbol Asset symbol. Example: \"DAI\"\n * @return price Min price from all the oracles, in USD with 8 decimal digits.\n **/\n function priceMin(string calldata symbol)\n external\n view\n returns (uint256 price)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n uint256 ep;\n uint256 p; //holder variables\n price = MAX_INT;\n if (config.ethOracles.length > 0) {\n ep = MAX_INT;\n for (uint256 i = 0; i < config.ethOracles.length; i++) {\n p = IEthUsdOracle(config.ethOracles[i]).tokEthPrice(symbol);\n if (ep > p) {\n ep = p;\n }\n }\n price = ep;\n ep = MAX_INT;\n for (uint256 i = 0; i < ethUsdOracles.length; i++) {\n p = IEthUsdOracle(ethUsdOracles[i]).ethUsdPrice();\n if (ep > p) {\n ep = p;\n }\n }\n if (price != MAX_INT && ep != MAX_INT) {\n // tokEthPrice has precision of 8 which ethUsdPrice has precision of 6\n // we want precision of 8\n price = (price * ep) / 1e6;\n }\n }\n\n if (config.usdOracles.length > 0) {\n for (uint256 i = 0; i < config.usdOracles.length; i++) {\n // upscale by 2 since price oracles are precision 6\n p = IPriceOracle(config.usdOracles[i]).price(symbol) * 1e2;\n if (price > p) {\n price = p;\n }\n }\n }\n require(price <= maxDrift, \"Price exceeds maxDrift\");\n require(price >= minDrift, \"Price below minDrift\");\n require(\n price != MAX_INT,\n \"None of our oracles returned a valid min price!\"\n );\n }\n\n /**\n * @notice Returns max price of an asset in USD.\n * @return symbol Asset symbol. Example: \"DAI\"\n * @return price Max price from all the oracles, in USD with 8 decimal digits.\n **/\n function priceMax(string calldata symbol)\n external\n view\n returns (uint256 price)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n uint256 ep;\n uint256 p; //holder variables\n price = 0;\n if (config.ethOracles.length > 0) {\n ep = 0;\n for (uint256 i = 0; i < config.ethOracles.length; i++) {\n p = IEthUsdOracle(config.ethOracles[i]).tokEthPrice(symbol);\n if (ep < p) {\n ep = p;\n }\n }\n price = ep;\n ep = 0;\n for (uint256 i = 0; i < ethUsdOracles.length; i++) {\n p = IEthUsdOracle(ethUsdOracles[i]).ethUsdPrice();\n if (ep < p) {\n ep = p;\n }\n }\n if (price != 0 && ep != 0) {\n // tokEthPrice has precision of 8 which ethUsdPrice has precision of 6\n // we want precision of 8\n price = (price * ep) / 1e6;\n }\n }\n\n if (config.usdOracles.length > 0) {\n for (uint256 i = 0; i < config.usdOracles.length; i++) {\n // upscale by 2 since price oracles are precision 6\n p = IPriceOracle(config.usdOracles[i]).price(symbol) * 1e2;\n if (price < p) {\n price = p;\n }\n }\n }\n\n require(price <= maxDrift, \"Price exceeds maxDrift\");\n require(price >= minDrift, \"Price below minDrift\");\n require(price != 0, \"None of our oracles returned a valid max price!\");\n }\n\n /**\n * @notice Returns the length of the usdOracles array for a given token\n * @param symbol Asset symbol. Example: \"DAI\"\n * @return length of the USD oracles array\n **/\n function getTokenUSDOraclesLength(string calldata symbol)\n external\n view\n returns (uint256)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n return config.usdOracles.length;\n }\n\n /**\n * @notice Returns the address of a specific USD oracle\n * @param symbol Asset symbol. Example: \"DAI\"\n * @param idx Index of the array value to return\n * @return address of the oracle\n **/\n function getTokenUSDOracle(string calldata symbol, uint256 idx)\n external\n view\n returns (address)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n return config.usdOracles[idx];\n }\n\n /**\n * @notice Returns the length of the ethOracles array for a given token\n * @param symbol Asset symbol. Example: \"DAI\"\n * @return length of the ETH oracles array\n **/\n function getTokenETHOraclesLength(string calldata symbol)\n external\n view\n returns (uint256)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n return config.ethOracles.length;\n }\n\n /**\n * @notice Returns the address of a specific ETH oracle\n * @param symbol Asset symbol. Example: \"DAI\"\n * @param idx Index of the array value to return\n * @return address of the oracle\n **/\n function getTokenETHOracle(string calldata symbol, uint256 idx)\n external\n view\n returns (address)\n {\n MixConfig storage config = configs[keccak256(abi.encodePacked(symbol))];\n return config.ethOracles[idx];\n }\n}\n" + }, + "contracts/interfaces/IPriceOracle.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IPriceOracle {\n /**\n * @dev returns the asset price in USD, 6 decimal digits.\n * Compatible with the Open Price Feed.\n */\n function price(string calldata symbol) external view returns (uint256);\n}\n" + }, + "contracts/interfaces/IEthUsdOracle.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IEthUsdOracle {\n /**\n * @notice Returns ETH price in USD.\n * @return Price in USD with 6 decimal digits.\n */\n function ethUsdPrice() external view returns (uint256);\n\n /**\n * @notice Returns token price in USD.\n * @param symbol. Asset symbol. For ex. \"DAI\".\n * @return Price in USD with 6 decimal digits.\n */\n function tokUsdPrice(string calldata symbol)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the asset price in ETH.\n * @param symbol. Asset symbol. For ex. \"DAI\".\n * @return Price in ETH with 8 decimal digits.\n */\n function tokEthPrice(string calldata symbol)\n external\n view\n returns (uint256);\n}\n\ninterface IViewEthUsdOracle {\n /**\n * @notice Returns ETH price in USD.\n * @return Price in USD with 6 decimal digits.\n */\n function ethUsdPrice() external view returns (uint256);\n\n /**\n * @notice Returns token price in USD.\n * @param symbol. Asset symbol. For ex. \"DAI\".\n * @return Price in USD with 6 decimal digits.\n */\n function tokUsdPrice(string calldata symbol)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the asset price in ETH.\n * @param symbol. Asset symbol. For ex. \"DAI\".\n * @return Price in ETH with 8 decimal digits.\n */\n function tokEthPrice(string calldata symbol)\n external\n view\n returns (uint256);\n}\n" + }, + "contracts/interfaces/IMinMaxOracle.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IMinMaxOracle {\n //Assuming 8 decimals\n function priceMin(string calldata symbol) external view returns (uint256);\n\n function priceMax(string calldata symbol) external view returns (uint256);\n}\n" + }, + "contracts/mocks/MockOracle.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../interfaces/IPriceOracle.sol\";\nimport \"../interfaces/IMinMaxOracle.sol\";\n\n/**\n * Mock of both price Oracle and min max oracles\n */\ncontract MockOracle is IPriceOracle, IMinMaxOracle {\n mapping(bytes32 => uint256) prices;\n mapping(bytes32 => uint256[]) pricesMinMax;\n uint256 ethMin;\n uint256 ethMax;\n\n /**\n * @dev returns the asset price in USD, 6 decimal digits.\n * Compatible with the Open Price Feed.\n */\n function price(string calldata symbol) external view returns (uint256) {\n return prices[keccak256(abi.encodePacked(symbol))];\n }\n\n /**\n * @dev sets the price of the asset in USD, 6 decimal digits\n *\n */\n function setPrice(string calldata symbol, uint256 _price) external {\n prices[keccak256(abi.encodePacked(symbol))] = _price;\n }\n\n /**\n * @dev sets the min and max price of ETH in USD, 6 decimal digits\n *\n */\n function setEthPriceMinMax(uint256 _min, uint256 _max) external {\n ethMin = _min;\n ethMax = _max;\n }\n\n /**\n * @dev sets the prices Min Max for a specific symbol in ETH, 8 decimal digits\n *\n */\n function setTokPriceMinMax(\n string calldata symbol,\n uint256 _min,\n uint256 _max\n ) external {\n pricesMinMax[keccak256(abi.encodePacked(symbol))] = [_min, _max];\n }\n\n /**\n * @dev get the price of asset in ETH, 8 decimal digits.\n */\n function priceMin(string calldata symbol) external view returns (uint256) {\n uint256[] storage pMinMax = pricesMinMax[keccak256(\n abi.encodePacked(symbol)\n )];\n return (pMinMax[0] * ethMin) / 1e6;\n }\n\n /**\n * @dev get the price of asset in USD, 8 decimal digits.\n * Not needed for now\n */\n function priceMax(string calldata symbol) external view returns (uint256) {\n uint256[] storage pMinMax = pricesMinMax[keccak256(\n abi.encodePacked(symbol)\n )];\n return (pMinMax[1] * ethMax) / 1e6;\n }\n}\n" + }, + "contracts/oracle/ChainlinkOracle.sol": { + "content": "// DEPRECATED - This contract is no longer used in production\npragma solidity 0.5.11;\n\n/**\n * @title OUSD ChainlinkOracle Contract\n * @author Origin Protocol Inc\n */\nimport \"../interfaces/chainlink/AggregatorV3Interface.sol\";\nimport { IPriceOracle } from \"../interfaces/IPriceOracle.sol\";\nimport { IEthUsdOracle } from \"../interfaces/IEthUsdOracle.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\ncontract ChainlinkOracle is IEthUsdOracle, IPriceOracle, Governable {\n event FeedRegistered(address _feed, string _symbol, bool _directToUsd);\n\n address ethFeed;\n\n struct FeedConfig {\n address feed;\n uint8 decimals;\n bool directToUsd;\n }\n\n mapping(bytes32 => FeedConfig) feeds;\n\n uint8 ethDecimals;\n\n string constant ethSymbol = \"ETH\";\n bytes32 constant ethHash = keccak256(abi.encodePacked(ethSymbol));\n\n constructor(address ethFeed_) public {\n ethFeed = ethFeed_;\n ethDecimals = AggregatorV3Interface(ethFeed_).decimals();\n }\n\n function registerFeed(\n address feed,\n string memory symbol,\n bool directToUsd\n ) public onlyGovernor {\n FeedConfig storage config = feeds[keccak256(abi.encodePacked(symbol))];\n\n config.feed = feed;\n config.decimals = AggregatorV3Interface(feed).decimals();\n config.directToUsd = directToUsd;\n\n emit FeedRegistered(feed, symbol, directToUsd);\n }\n\n function getLatestPrice(address feed) internal view returns (int256) {\n (\n uint80 roundID,\n int256 price,\n uint256 startedAt,\n uint256 timeStamp,\n uint80 answeredInRound\n ) = AggregatorV3Interface(feed).latestRoundData();\n // silence\n roundID;\n startedAt;\n timeStamp;\n answeredInRound;\n return price;\n }\n\n function ethUsdPrice() external view returns (uint256) {\n return (uint256(getLatestPrice(ethFeed)) /\n (uint256(10)**(ethDecimals - 6)));\n }\n\n function tokUsdPrice(string calldata symbol)\n external\n view\n returns (uint256)\n {\n bytes32 tokenSymbolHash = keccak256(abi.encodePacked(symbol));\n FeedConfig storage config = feeds[tokenSymbolHash];\n int256 tPrice = getLatestPrice(config.feed);\n\n require(config.directToUsd, \"Price is not direct to usd\");\n require(tPrice > 0, \"Price must be greater than zero\");\n return uint256(tPrice);\n }\n\n function tokEthPrice(string calldata symbol)\n external\n view\n returns (uint256)\n {\n bytes32 tokenSymbolHash = keccak256(abi.encodePacked(symbol));\n FeedConfig storage config = feeds[tokenSymbolHash];\n int256 tPrice = getLatestPrice(config.feed);\n\n require(!config.directToUsd, \"Price is not in terms of ETH\");\n require(tPrice > 0, \"Price must be greater than zero\");\n //attempt to return 8 digit precision here\n return uint256(tPrice) / (uint256(10)**(config.decimals - 8));\n }\n\n // This actually calculate the latest price from outside oracles\n // It's a view but substantially more costly in terms of calculation\n function price(string calldata symbol) external view returns (uint256) {\n bytes32 tokenSymbolHash = keccak256(abi.encodePacked(symbol));\n\n if (ethHash == tokenSymbolHash) {\n return (uint256(getLatestPrice(ethFeed)) /\n (uint256(10)**(ethDecimals - 6)));\n } else {\n FeedConfig storage config = feeds[tokenSymbolHash];\n int256 tPrice = getLatestPrice(config.feed);\n\n if (config.directToUsd) {\n require(tPrice > 0, \"Price must be greater than zero\");\n return uint256(tPrice);\n } else {\n int256 ethPrice = getLatestPrice(ethFeed); // grab the eth price from the open oracle\n require(\n tPrice > 0 && ethPrice > 0,\n \"Both eth and price must be greater than zero\"\n );\n //not actually sure why it's 6 units here, this is just to match with openoracle for now\n return\n mul(uint256(tPrice), uint256(ethPrice)) /\n (uint256(10)**(ethDecimals + config.decimals - 6));\n }\n }\n }\n\n /// @dev Overflow proof multiplication\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"multiplication overflow\");\n return c;\n }\n}\n" + }, + "contracts/interfaces/chainlink/AggregatorV3Interface.sol": { + "content": "pragma solidity ^0.5.11;\n\ninterface AggregatorV3Interface {\n function decimals() external view returns (uint8);\n\n function description() external view returns (string memory);\n\n function version() external view returns (uint256);\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n}\n" + }, + "contracts/oracle/OracleRouter.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../interfaces/chainlink/AggregatorV3Interface.sol\";\nimport { IOracle } from \"../interfaces/IOracle.sol\";\n\ncontract OracleRouterBase is IOracle {\n uint256 constant MIN_DRIFT = uint256(70000000);\n uint256 constant MAX_DRIFT = uint256(130000000);\n\n /**\n * @dev The price feed contract to use for a particular asset.\n * @param asset address of the asset\n */\n function feed(address asset) internal view returns (address);\n\n /**\n * @notice Returns the total price in 8 digit USD for a given asset.\n * @param asset address of the asset\n * @return uint256 USD price of 1 of the asset, in 8 decimal fixed\n */\n function price(address asset) external view returns (uint256) {\n address _feed = feed(asset);\n require(_feed != address(0), \"Asset not available\");\n (\n uint80 roundID,\n int256 _iprice,\n uint256 startedAt,\n uint256 timeStamp,\n uint80 answeredInRound\n ) = AggregatorV3Interface(_feed).latestRoundData();\n uint256 _price = uint256(_iprice);\n require(_price <= MAX_DRIFT, \"Oracle: Price exceeds max\");\n require(_price >= MIN_DRIFT, \"Oracle: Price under min\");\n return uint256(_price);\n }\n}\n\ncontract OracleRouter is OracleRouterBase {\n /**\n * @dev The price feed contract to use for a particular asset.\n * @param asset address of the asset\n */\n function feed(address asset) internal view returns (address) {\n // DAI\n if (asset == address(0x6B175474E89094C44Da98b954EedeAC495271d0F)) {\n return address(0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9);\n // USDC\n } else if (\n asset == address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)\n ) {\n return address(0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6);\n // USDT\n } else if (\n asset == address(0xdAC17F958D2ee523a2206206994597C13D831ec7)\n ) {\n return address(0x3E7d1eAB13ad0104d2750B8863b489D65364e32D);\n } else {\n require(false, \"Asset not available\");\n }\n }\n}\n\ncontract OracleRouterDev is OracleRouterBase {\n mapping(address => address) public assetToFeed;\n\n function setFeed(address _asset, address _feed) external {\n assetToFeed[_asset] = _feed;\n }\n\n /**\n * @dev The price feed contract to use for a particular asset.\n * @param asset address of the asset\n */\n function feed(address asset) internal view returns (address) {\n return assetToFeed[asset];\n }\n}\n" + }, + "contracts/vault/VaultCore.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Vault Contract\n * @notice The Vault contract stores assets. On a deposit, OUSD will be minted\n and sent to the depositor. On a withdrawal, OUSD will be burned and\n assets will be sent to the withdrawer. The Vault accepts deposits of\n interest form yield bearing strategies which will modify the supply\n of OUSD.\n * @author Origin Protocol Inc\n */\n\nimport \"./VaultStorage.sol\";\nimport { IOracle } from \"../interfaces/IOracle.sol\";\nimport { IVault } from \"../interfaces/IVault.sol\";\nimport { IBuyback } from \"../interfaces/IBuyback.sol\";\n\ncontract VaultCore is VaultStorage {\n uint256 constant MAX_UINT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\n\n /**\n * @dev Verifies that the rebasing is not paused.\n */\n modifier whenNotRebasePaused() {\n require(!rebasePaused, \"Rebasing paused\");\n _;\n }\n\n /**\n * @dev Verifies that the deposits are not paused.\n */\n modifier whenNotCapitalPaused() {\n require(!capitalPaused, \"Capital paused\");\n _;\n }\n\n /**\n * @dev Deposit a supported asset and mint OUSD.\n * @param _asset Address of the asset being deposited\n * @param _amount Amount of the asset being deposited\n * @param _minimumOusdAmount Minimum OUSD to mint\n */\n function mint(\n address _asset,\n uint256 _amount,\n uint256 _minimumOusdAmount\n ) external whenNotCapitalPaused nonReentrant {\n require(assets[_asset].isSupported, \"Asset is not supported\");\n require(_amount > 0, \"Amount must be greater than 0\");\n\n uint256 price = IOracle(priceProvider).price(_asset);\n if (price > 1e8) {\n price = 1e8;\n }\n uint256 assetDecimals = Helpers.getDecimals(_asset);\n uint256 unitAdjustedDeposit = _amount.scaleBy(int8(18 - assetDecimals));\n uint256 priceAdjustedDeposit = _amount.mulTruncateScale(\n price.scaleBy(int8(10)), // 18-8 because oracles have 8 decimals precision\n 10**assetDecimals\n );\n\n if (_minimumOusdAmount > 0) {\n require(\n priceAdjustedDeposit >= _minimumOusdAmount,\n \"Mint amount lower than minimum\"\n );\n }\n\n emit Mint(msg.sender, priceAdjustedDeposit);\n\n // Rebase must happen before any transfers occur.\n if (unitAdjustedDeposit >= rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n\n // Mint matching OUSD\n oUSD.mint(msg.sender, priceAdjustedDeposit);\n\n // Transfer the deposited coins to the vault\n IERC20 asset = IERC20(_asset);\n asset.safeTransferFrom(msg.sender, address(this), _amount);\n\n if (unitAdjustedDeposit >= autoAllocateThreshold) {\n _allocate();\n }\n }\n\n /**\n * @dev Mint for multiple assets in the same call.\n * @param _assets Addresses of assets being deposited\n * @param _amounts Amount of each asset at the same index in the _assets\n * to deposit.\n * @param _minimumOusdAmount Minimum OUSD to mint\n */\n function mintMultiple(\n address[] calldata _assets,\n uint256[] calldata _amounts,\n uint256 _minimumOusdAmount\n ) external whenNotCapitalPaused nonReentrant {\n require(_assets.length == _amounts.length, \"Parameter length mismatch\");\n\n uint256 unitAdjustedTotal = 0;\n uint256 priceAdjustedTotal = 0;\n uint256[] memory assetPrices = _getAssetPrices(false);\n for (uint256 j = 0; j < _assets.length; j++) {\n // In memoriam\n require(assets[_assets[j]].isSupported, \"Asset is not supported\");\n require(_amounts[j] > 0, \"Amount must be greater than 0\");\n for (uint256 i = 0; i < allAssets.length; i++) {\n if (_assets[j] == allAssets[i]) {\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\n uint256 price = assetPrices[i];\n if (price > 1e18) {\n price = 1e18;\n }\n unitAdjustedTotal = unitAdjustedTotal.add(\n _amounts[j].scaleBy(int8(18 - assetDecimals))\n );\n priceAdjustedTotal = priceAdjustedTotal.add(\n _amounts[j].mulTruncateScale(price, 10**assetDecimals)\n );\n }\n }\n }\n\n if (_minimumOusdAmount > 0) {\n require(\n priceAdjustedTotal >= _minimumOusdAmount,\n \"Mint amount lower than minimum\"\n );\n }\n\n emit Mint(msg.sender, priceAdjustedTotal);\n\n // Rebase must happen before any transfers occur.\n if (unitAdjustedTotal >= rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n\n oUSD.mint(msg.sender, priceAdjustedTotal);\n\n for (uint256 i = 0; i < _assets.length; i++) {\n IERC20 asset = IERC20(_assets[i]);\n asset.safeTransferFrom(msg.sender, address(this), _amounts[i]);\n }\n\n if (unitAdjustedTotal >= autoAllocateThreshold) {\n _allocate();\n }\n }\n\n /**\n * @dev Withdraw a supported asset and burn OUSD.\n * @param _amount Amount of OUSD to burn\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\n */\n function redeem(uint256 _amount, uint256 _minimumUnitAmount)\n public\n whenNotCapitalPaused\n nonReentrant\n {\n if (_amount > rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n _redeem(_amount, _minimumUnitAmount);\n }\n\n /**\n * @dev Withdraw a supported asset and burn OUSD.\n * @param _amount Amount of OUSD to burn\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\n */\n function _redeem(uint256 _amount, uint256 _minimumUnitAmount) internal {\n require(_amount > 0, \"Amount must be greater than 0\");\n\n uint256 _totalSupply = oUSD.totalSupply();\n uint256 _backingValue = _totalValue();\n\n if (maxSupplyDiff > 0) {\n // Allow a max difference of maxSupplyDiff% between\n // backing assets value and OUSD total supply\n uint256 diff = _totalSupply.divPrecisely(_backingValue);\n\n require(\n (diff > 1e18 ? diff.sub(1e18) : uint256(1e18).sub(diff)) <=\n maxSupplyDiff,\n \"Backing supply liquidity error\"\n );\n }\n\n emit Redeem(msg.sender, _amount);\n\n // Calculate redemption outputs\n uint256[] memory outputs = _calculateRedeemOutputs(_amount);\n // Send outputs\n for (uint256 i = 0; i < allAssets.length; i++) {\n if (outputs[i] == 0) continue;\n\n IERC20 asset = IERC20(allAssets[i]);\n\n if (asset.balanceOf(address(this)) >= outputs[i]) {\n // Use Vault funds first if sufficient\n asset.safeTransfer(msg.sender, outputs[i]);\n } else {\n address strategyAddr = assetDefaultStrategies[allAssets[i]];\n if (strategyAddr != address(0)) {\n // Nothing in Vault, but something in Strategy, send from there\n IStrategy strategy = IStrategy(strategyAddr);\n strategy.withdraw(msg.sender, allAssets[i], outputs[i]);\n } else {\n // Cant find funds anywhere\n revert(\"Liquidity error\");\n }\n }\n }\n\n if (_minimumUnitAmount > 0) {\n uint256 unitTotal = 0;\n for (uint256 i = 0; i < outputs.length; i++) {\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\n unitTotal = unitTotal.add(\n outputs[i].scaleBy(int8(18 - assetDecimals))\n );\n }\n require(\n unitTotal >= _minimumUnitAmount,\n \"Redeem amount lower than minimum\"\n );\n }\n\n oUSD.burn(msg.sender, _amount);\n\n // Until we can prove that we won't affect the prices of our assets\n // by withdrawing them, this should be here.\n // It's possible that a strategy was off on its asset total, perhaps\n // a reward token sold for more or for less than anticipated.\n if (_amount > rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n }\n\n /**\n * @notice Withdraw a supported asset and burn all OUSD.\n * @param _minimumUnitAmount Minimum stablecoin units to receive in return\n */\n function redeemAll(uint256 _minimumUnitAmount)\n external\n whenNotCapitalPaused\n nonReentrant\n {\n // Unfortunately we have to do balanceOf twice, the rebase may change\n // the account balance\n if (oUSD.balanceOf(msg.sender) > rebaseThreshold && !rebasePaused) {\n _rebase();\n }\n _redeem(oUSD.balanceOf(msg.sender), _minimumUnitAmount);\n }\n\n /**\n * @notice Allocate unallocated funds on Vault to strategies.\n * @dev Allocate unallocated funds on Vault to strategies.\n **/\n function allocate() public whenNotCapitalPaused nonReentrant {\n _allocate();\n }\n\n /**\n * @notice Allocate unallocated funds on Vault to strategies.\n * @dev Allocate unallocated funds on Vault to strategies.\n **/\n function _allocate() internal {\n uint256 vaultValue = _totalValueInVault();\n // Nothing in vault to allocate\n if (vaultValue == 0) return;\n uint256 strategiesValue = _totalValueInStrategies();\n // We have a method that does the same as this, gas optimisation\n uint256 calculatedTotalValue = vaultValue.add(strategiesValue);\n\n // We want to maintain a buffer on the Vault so calculate a percentage\n // modifier to multiply each amount being allocated by to enforce the\n // vault buffer\n uint256 vaultBufferModifier;\n if (strategiesValue == 0) {\n // Nothing in Strategies, allocate 100% minus the vault buffer to\n // strategies\n vaultBufferModifier = uint256(1e18).sub(vaultBuffer);\n } else {\n vaultBufferModifier = vaultBuffer.mul(calculatedTotalValue).div(\n vaultValue\n );\n if (1e18 > vaultBufferModifier) {\n // E.g. 1e18 - (1e17 * 10e18)/5e18 = 8e17\n // (5e18 * 8e17) / 1e18 = 4e18 allocated from Vault\n vaultBufferModifier = uint256(1e18).sub(vaultBufferModifier);\n } else {\n // We need to let the buffer fill\n return;\n }\n }\n if (vaultBufferModifier == 0) return;\n\n // Iterate over all assets in the Vault and allocate the the appropriate\n // strategy\n for (uint256 i = 0; i < allAssets.length; i++) {\n IERC20 asset = IERC20(allAssets[i]);\n uint256 assetBalance = asset.balanceOf(address(this));\n // No balance, nothing to do here\n if (assetBalance == 0) continue;\n\n // Multiply the balance by the vault buffer modifier and truncate\n // to the scale of the asset decimals\n uint256 allocateAmount = assetBalance.mulTruncate(\n vaultBufferModifier\n );\n\n address depositStrategyAddr = assetDefaultStrategies[address(\n asset\n )];\n\n if (depositStrategyAddr != address(0) && allocateAmount > 0) {\n IStrategy strategy = IStrategy(depositStrategyAddr);\n // Transfer asset to Strategy and call deposit method to\n // mint or take required action\n asset.safeTransfer(address(strategy), allocateAmount);\n strategy.deposit(address(asset), allocateAmount);\n }\n }\n\n // Harvest for all reward tokens above reward liquidation threshold\n for (uint256 i = 0; i < allStrategies.length; i++) {\n IStrategy strategy = IStrategy(allStrategies[i]);\n address rewardTokenAddress = strategy.rewardTokenAddress();\n if (rewardTokenAddress != address(0)) {\n uint256 liquidationThreshold = strategy\n .rewardLiquidationThreshold();\n if (liquidationThreshold == 0) {\n // No threshold set, always harvest from strategy\n IVault(address(this)).harvest(allStrategies[i]);\n } else {\n // Check balance against liquidation threshold\n // Note some strategies don't hold the reward token balance\n // on their contract so the liquidation threshold should be\n // set to 0\n IERC20 rewardToken = IERC20(rewardTokenAddress);\n uint256 rewardTokenAmount = rewardToken.balanceOf(\n allStrategies[i]\n );\n if (rewardTokenAmount >= liquidationThreshold) {\n IVault(address(this)).harvest(allStrategies[i]);\n }\n }\n }\n }\n\n // Trigger OGN Buyback\n IBuyback(trusteeAddress).swap();\n }\n\n /**\n * @dev Calculate the total value of assets held by the Vault and all\n * strategies and update the supply of OUSD.\n */\n function rebase() public whenNotRebasePaused nonReentrant {\n _rebase();\n }\n\n /**\n * @dev Calculate the total value of assets held by the Vault and all\n * strategies and update the supply of OUSD, optionaly sending a\n * portion of the yield to the trustee.\n */\n function _rebase() internal whenNotRebasePaused {\n uint256 ousdSupply = oUSD.totalSupply();\n if (ousdSupply == 0) {\n return;\n }\n uint256 vaultValue = _totalValue();\n\n // Yield fee collection\n address _trusteeAddress = trusteeAddress; // gas savings\n if (_trusteeAddress != address(0) && (vaultValue > ousdSupply)) {\n uint256 yield = vaultValue.sub(ousdSupply);\n uint256 fee = yield.mul(trusteeFeeBps).div(10000);\n require(yield > fee, \"Fee must not be greater than yield\");\n if (fee > 0) {\n oUSD.mint(_trusteeAddress, fee);\n }\n emit YieldDistribution(_trusteeAddress, yield, fee);\n }\n\n // Only rachet OUSD supply upwards\n ousdSupply = oUSD.totalSupply(); // Final check should use latest value\n if (vaultValue > ousdSupply) {\n oUSD.changeSupply(vaultValue);\n }\n }\n\n /**\n * @dev Determine the total value of assets held by the vault and its\n * strategies.\n * @return uint256 value Total value in USD (1e18)\n */\n function totalValue() external view returns (uint256 value) {\n value = _totalValue();\n }\n\n /**\n * @dev Internal Calculate the total value of the assets held by the\n * vault and its strategies.\n * @return uint256 value Total value in USD (1e18)\n */\n function _totalValue() internal view returns (uint256 value) {\n return _totalValueInVault().add(_totalValueInStrategies());\n }\n\n /**\n * @dev Internal to calculate total value of all assets held in Vault.\n * @return uint256 Total value in ETH (1e18)\n */\n function _totalValueInVault() internal view returns (uint256 value) {\n for (uint256 y = 0; y < allAssets.length; y++) {\n IERC20 asset = IERC20(allAssets[y]);\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\n uint256 balance = asset.balanceOf(address(this));\n if (balance > 0) {\n value = value.add(balance.scaleBy(int8(18 - assetDecimals)));\n }\n }\n }\n\n /**\n * @dev Internal to calculate total value of all assets held in Strategies.\n * @return uint256 Total value in ETH (1e18)\n */\n function _totalValueInStrategies() internal view returns (uint256 value) {\n for (uint256 i = 0; i < allStrategies.length; i++) {\n value = value.add(_totalValueInStrategy(allStrategies[i]));\n }\n }\n\n /**\n * @dev Internal to calculate total value of all assets held by strategy.\n * @param _strategyAddr Address of the strategy\n * @return uint256 Total value in ETH (1e18)\n */\n function _totalValueInStrategy(address _strategyAddr)\n internal\n view\n returns (uint256 value)\n {\n IStrategy strategy = IStrategy(_strategyAddr);\n for (uint256 y = 0; y < allAssets.length; y++) {\n uint256 assetDecimals = Helpers.getDecimals(allAssets[y]);\n if (strategy.supportsAsset(allAssets[y])) {\n uint256 balance = strategy.checkBalance(allAssets[y]);\n if (balance > 0) {\n value = value.add(\n balance.scaleBy(int8(18 - assetDecimals))\n );\n }\n }\n }\n }\n\n /**\n * @notice Get the balance of an asset held in Vault and all strategies.\n * @param _asset Address of asset\n * @return uint256 Balance of asset in decimals of asset\n */\n function checkBalance(address _asset) external view returns (uint256) {\n return _checkBalance(_asset);\n }\n\n /**\n * @notice Get the balance of an asset held in Vault and all strategies.\n * @param _asset Address of asset\n * @return uint256 Balance of asset in decimals of asset\n */\n function _checkBalance(address _asset)\n internal\n view\n returns (uint256 balance)\n {\n IERC20 asset = IERC20(_asset);\n balance = asset.balanceOf(address(this));\n for (uint256 i = 0; i < allStrategies.length; i++) {\n IStrategy strategy = IStrategy(allStrategies[i]);\n if (strategy.supportsAsset(_asset)) {\n balance = balance.add(strategy.checkBalance(_asset));\n }\n }\n }\n\n /**\n * @notice Get the balance of all assets held in Vault and all strategies.\n * @return uint256 Balance of all assets (1e18)\n */\n function _checkBalance() internal view returns (uint256 balance) {\n for (uint256 i = 0; i < allAssets.length; i++) {\n uint256 assetDecimals = Helpers.getDecimals(allAssets[i]);\n balance = balance.add(\n _checkBalance(allAssets[i]).scaleBy(int8(18 - assetDecimals))\n );\n }\n }\n\n /**\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\n * coins that will be returned\n */\n function calculateRedeemOutputs(uint256 _amount)\n external\n view\n returns (uint256[] memory)\n {\n return _calculateRedeemOutputs(_amount);\n }\n\n /**\n * @notice Calculate the outputs for a redeem function, i.e. the mix of\n * coins that will be returned.\n * @return Array of amounts respective to the supported assets\n */\n function _calculateRedeemOutputs(uint256 _amount)\n internal\n view\n returns (uint256[] memory outputs)\n {\n // We always give out coins in proportion to how many we have,\n // Now if all coins were the same value, this math would easy,\n // just take the percentage of each coin, and multiply by the\n // value to be given out. But if coins are worth more than $1,\n // then we would end up handing out too many coins. We need to\n // adjust by the total value of coins.\n //\n // To do this, we total up the value of our coins, by their\n // percentages. Then divide what we would otherwise give out by\n // this number.\n //\n // Let say we have 100 DAI at $1.06 and 200 USDT at $1.00.\n // So for every 1 DAI we give out, we'll be handing out 2 USDT\n // Our total output ratio is: 33% * 1.06 + 66% * 1.00 = 1.02\n //\n // So when calculating the output, we take the percentage of\n // each coin, times the desired output value, divided by the\n // totalOutputRatio.\n //\n // For example, withdrawing: 30 OUSD:\n // DAI 33% * 30 / 1.02 = 9.80 DAI\n // USDT = 66 % * 30 / 1.02 = 19.60 USDT\n //\n // Checking these numbers:\n // 9.80 DAI * 1.06 = $10.40\n // 19.60 USDT * 1.00 = $19.60\n //\n // And so the user gets $10.40 + $19.60 = $30 worth of value.\n\n uint256 assetCount = getAssetCount();\n uint256[] memory assetPrices = _getAssetPrices(true);\n uint256[] memory assetBalances = new uint256[](assetCount);\n uint256[] memory assetDecimals = new uint256[](assetCount);\n uint256 totalBalance = 0;\n uint256 totalOutputRatio = 0;\n outputs = new uint256[](assetCount);\n\n // Calculate redeem fee\n if (redeemFeeBps > 0) {\n uint256 redeemFee = _amount.mul(redeemFeeBps).div(10000);\n _amount = _amount.sub(redeemFee);\n }\n\n // Calculate assets balances and decimals once,\n // for a large gas savings.\n for (uint256 i = 0; i < allAssets.length; i++) {\n uint256 balance = _checkBalance(allAssets[i]);\n uint256 decimals = Helpers.getDecimals(allAssets[i]);\n assetBalances[i] = balance;\n assetDecimals[i] = decimals;\n totalBalance = totalBalance.add(\n balance.scaleBy(int8(18 - decimals))\n );\n }\n // Calculate totalOutputRatio\n for (uint256 i = 0; i < allAssets.length; i++) {\n uint256 price = assetPrices[i];\n // Never give out more than one\n // stablecoin per dollar of OUSD\n if (price < 1e18) {\n price = 1e18;\n }\n uint256 ratio = assetBalances[i]\n .scaleBy(int8(18 - assetDecimals[i]))\n .mul(price)\n .div(totalBalance);\n totalOutputRatio = totalOutputRatio.add(ratio);\n }\n // Calculate final outputs\n uint256 factor = _amount.divPrecisely(totalOutputRatio);\n for (uint256 i = 0; i < allAssets.length; i++) {\n outputs[i] = assetBalances[i].mul(factor).div(totalBalance);\n }\n }\n\n /**\n * @notice Get an array of the supported asset prices in USD.\n * @return uint256[] Array of asset prices in USD (1e18)\n */\n function _getAssetPrices(bool useMax)\n internal\n view\n returns (uint256[] memory assetPrices)\n {\n assetPrices = new uint256[](getAssetCount());\n\n IOracle oracle = IOracle(priceProvider);\n // Price from Oracle is returned with 8 decimals\n // _amount is in assetDecimals\n for (uint256 i = 0; i < allAssets.length; i++) {\n assetPrices[i] = oracle.price(allAssets[i]).scaleBy(int8(18 - 8));\n }\n }\n\n /***************************************\n Utils\n ****************************************/\n\n /**\n * @dev Return the number of assets suppported by the Vault.\n */\n function getAssetCount() public view returns (uint256) {\n return allAssets.length;\n }\n\n /**\n * @dev Return all asset addresses in order\n */\n function getAllAssets() external view returns (address[] memory) {\n return allAssets;\n }\n\n /**\n * @dev Return the number of strategies active on the Vault.\n */\n function getStrategyCount() external view returns (uint256) {\n return allStrategies.length;\n }\n\n function isSupportedAsset(address _asset) external view returns (bool) {\n return assets[_asset].isSupported;\n }\n\n /**\n * @dev Falldown to the admin implementation\n * @notice This is a catch all for all functions not declared in core\n */\n function() external payable {\n bytes32 slot = adminImplPosition;\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize)\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas, sload(slot), 0, calldatasize, 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize)\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize)\n }\n default {\n return(0, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/interfaces/IVault.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IVault {\n event AssetSupported(address _asset);\n event StrategyApproved(address _addr);\n event StrategyRemoved(address _addr);\n event Mint(address _addr, uint256 _value);\n event Redeem(address _addr, uint256 _value);\n event DepositsPaused();\n event DepositsUnpaused();\n\n // Governable.sol\n function transferGovernance(address _newGovernor) external;\n\n function claimGovernance() external;\n\n function governor() external view returns (address);\n\n // VaultAdmin.sol\n function setPriceProvider(address _priceProvider) external;\n\n function priceProvider() external view returns (address);\n\n function setRedeemFeeBps(uint256 _redeemFeeBps) external;\n\n function redeemFeeBps() external view returns (uint256);\n\n function setVaultBuffer(uint256 _vaultBuffer) external;\n\n function vaultBuffer() external view returns (uint256);\n\n function setAutoAllocateThreshold(uint256 _threshold) external;\n\n function autoAllocateThreshold() external view returns (uint256);\n\n function setRebaseThreshold(uint256 _threshold) external;\n\n function rebaseThreshold() external view returns (uint256);\n\n function setStrategistAddr(address _address) external;\n\n function strategistAddr() external view returns (address);\n\n function setUniswapAddr(address _address) external;\n\n function uniswapAddr() external view returns (address);\n\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;\n\n function maxSupplyDiff() external view returns (uint256);\n\n function setTrusteeAddress(address _address) external;\n\n function trusteeAddress() external view returns (address);\n\n function setTrusteeFeeBps(uint256 _basis) external;\n\n function trusteeFeeBps() external view returns (uint256);\n\n function supportAsset(address _asset) external;\n\n function approveStrategy(address _addr) external;\n\n function removeStrategy(address _addr) external;\n\n function setAssetDefaultStrategy(address _asset, address _strategy)\n external;\n\n function assetDefaultStrategies(address _asset)\n external\n view\n returns (address);\n\n function pauseRebase() external;\n\n function unpauseRebase() external;\n\n function rebasePaused() external view returns (bool);\n\n function pauseCapital() external;\n\n function unpauseCapital() external;\n\n function capitalPaused() external view returns (bool);\n\n function transferToken(address _asset, uint256 _amount) external;\n\n function harvest() external;\n\n function harvest(address _strategyAddr) external;\n\n function priceUSDMint(address asset) external view returns (uint256);\n\n function priceUSDRedeem(address asset) external view returns (uint256);\n\n function withdrawAllFromStrategy(address _strategyAddr) external;\n\n function withdrawAllFromStrategies() external;\n\n // VaultCore.sol\n function mint(\n address _asset,\n uint256 _amount,\n uint256 _minimumOusdAmount\n ) external;\n\n function mintMultiple(\n address[] calldata _assets,\n uint256[] calldata _amount,\n uint256 _minimumOusdAmount\n ) external;\n\n function redeem(uint256 _amount, uint256 _minimumUnitAmount) external;\n\n function redeemAll(uint256 _minimumUnitAmount) external;\n\n function allocate() external;\n\n function reallocate(\n address _strategyFromAddress,\n address _strategyToAddress,\n address[] calldata _assets,\n uint256[] calldata _amounts\n ) external;\n\n function rebase() external;\n\n function totalValue() external view returns (uint256 value);\n\n function checkBalance() external view returns (uint256);\n\n function checkBalance(address _asset) external view returns (uint256);\n\n function calculateRedeemOutputs(uint256 _amount)\n external\n view\n returns (uint256[] memory);\n\n function getAssetCount() external view returns (uint256);\n\n function getAllAssets() external view returns (address[] memory);\n\n function getStrategyCount() external view returns (uint256);\n\n function isSupportedAsset(address _asset) external view returns (bool);\n}\n" + }, + "contracts/interfaces/IBuyback.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IBuyback {\n function swap() external;\n}\n" + }, + "contracts/mocks/MockNonRebasing.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IVault } from \"../interfaces/IVault.sol\";\n\nimport { OUSD } from \"../token/OUSD.sol\";\n\ncontract MockNonRebasing {\n OUSD oUSD;\n\n function setOUSD(address _oUSDAddress) public {\n oUSD = OUSD(_oUSDAddress);\n }\n\n function rebaseOptIn() public {\n oUSD.rebaseOptIn();\n }\n\n function rebaseOptOut() public {\n oUSD.rebaseOptOut();\n }\n\n function transfer(address _to, uint256 _value) public {\n oUSD.transfer(_to, _value);\n }\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) public {\n oUSD.transferFrom(_from, _to, _value);\n }\n\n function increaseAllowance(address _spender, uint256 _addedValue) public {\n oUSD.increaseAllowance(_spender, _addedValue);\n }\n\n function mintOusd(\n address _vaultContract,\n address _asset,\n uint256 _amount\n ) public {\n IVault(_vaultContract).mint(_asset, _amount, 0);\n }\n\n function redeemOusd(address _vaultContract, uint256 _amount) public {\n IVault(_vaultContract).redeem(_amount, 0);\n }\n\n function approveFor(\n address _contract,\n address _spender,\n uint256 _addedValue\n ) public {\n IERC20(_contract).approve(_spender, _addedValue);\n }\n}\n" + }, + "contracts/flipper/FlipperDev.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../governance/Governable.sol\";\nimport \"../token/OUSD.sol\";\nimport \"../interfaces/Tether.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n// Contract to exchange usdt, usdc, dai from and to ousd.\n// - 1 to 1. No slippage\n// - Optimized for low gas usage\n// - No guarantee of availability\n\ncontract FlipperDev is Governable {\n using SafeERC20 for IERC20;\n\n uint256 constant MAXIMUM_PER_TRADE = (25000 * 1e18);\n\n // Settable coin addresses allow easy testing and use of mock currencies.\n IERC20 dai = IERC20(0);\n OUSD ousd = OUSD(0);\n IERC20 usdc = IERC20(0);\n Tether usdt = Tether(0);\n\n // ---------------------\n // Dev constructor\n // ---------------------\n constructor(\n address dai_,\n address ousd_,\n address usdc_,\n address usdt_\n ) public {\n dai = IERC20(dai_);\n ousd = OUSD(ousd_);\n usdc = IERC20(usdc_);\n usdt = Tether(usdt_);\n require(address(ousd) != address(0));\n require(address(dai) != address(0));\n require(address(usdc) != address(0));\n require(address(usdt) != address(0));\n }\n\n // -----------------\n // Trading functions\n // -----------------\n\n /// @notice Purchase OUSD with Dai\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithDai(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(dai.transferFrom(msg.sender, address(this), amount));\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for Dai\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForDai(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(dai.transfer(msg.sender, amount));\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n /// @notice Purchase OUSD with USDC\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithUsdc(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // Potential rounding error is an intentional tradeoff\n require(usdc.transferFrom(msg.sender, address(this), amount / 1e12));\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for USDC\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForUsdc(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(usdc.transfer(msg.sender, amount / 1e12));\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n /// @notice Purchase OUSD with USDT\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithUsdt(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // Potential rounding error is an intentional tradeoff\n // USDT does not return a boolean and reverts,\n // so no need for a require.\n usdt.transferFrom(msg.sender, address(this), amount / 1e12);\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for USDT\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForUsdt(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // USDT does not return a boolean and reverts,\n // so no need for a require.\n usdt.transfer(msg.sender, amount / 1e12);\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n // --------------------\n // Governance functions\n // --------------------\n\n /// @dev Opting into yield reduces the gas cost per transfer by about 4K, since\n /// ousd needs to do less accounting and one less storage write.\n function rebaseOptIn() external onlyGovernor nonReentrant {\n ousd.rebaseOptIn();\n }\n\n /// @notice Owner function to withdraw a specific amount of a token\n function withdraw(address token, uint256 amount)\n external\n onlyGovernor\n nonReentrant\n {\n IERC20(token).safeTransfer(_governor(), amount);\n }\n\n /// @notice Owner function to withdraw all tradable tokens\n /// @dev Equivalent to \"pausing\" the contract.\n function withdrawAll() external onlyGovernor nonReentrant {\n IERC20(dai).safeTransfer(_governor(), dai.balanceOf(address(this)));\n IERC20(ousd).safeTransfer(_governor(), ousd.balanceOf(address(this)));\n IERC20(address(usdt)).safeTransfer(\n _governor(),\n usdt.balanceOf(address(this))\n );\n IERC20(usdc).safeTransfer(_governor(), usdc.balanceOf(address(this)));\n }\n}\n" + }, + "contracts/interfaces/Tether.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface Tether {\n function transfer(address to, uint256 value) external;\n\n function transferFrom(\n address from,\n address to,\n uint256 value\n ) external;\n\n function balanceOf(address) external returns (uint256);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./IERC20.sol\";\n\n/**\n * @dev Optional functions from the ERC20 standard.\n */\ncontract ERC20Detailed is IERC20 {\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of\n * these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name, string memory symbol, uint8 decimals) public {\n _name = name;\n _symbol = symbol;\n _decimals = decimals;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view 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 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.\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 returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/mocks/MockOGN.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\";\n\nimport \"./WhitelistedPausableToken.sol\";\n\n/**\n * @title Origin token (OGN).\n *\n * @dev Token that allows minting, burning, and pausing by contract owner.\n * @dev Important note:\n * @dev There is a known race condition in the ERC20 standard on the approve() method.\n * @dev See details: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n * @dev The Origin token contract implements the increaseApproval() and decreaseApproval() methods.\n * @dev It is strongly recommended to use those methods rather than approve()\n * @dev when updating the token allowance.\n */\n// Removed ERC20Mintable since this is a Mock and we're just exposing the mint function directly\ncontract MockOGN is ERC20Burnable, WhitelistedPausableToken, ERC20Detailed {\n event AddCallSpenderWhitelist(address enabler, address spender);\n event RemoveCallSpenderWhitelist(address disabler, address spender);\n\n mapping(address => bool) public callSpenderWhitelist;\n\n // @dev Constructor that gives msg.sender all initial tokens.\n constructor(uint256 _initialSupply)\n public\n ERC20Detailed(\"OriginToken\", \"OGN\", 18)\n {\n owner = msg.sender;\n _mint(owner, _initialSupply);\n }\n\n // @dev Helper method for mocks testing to allow tests to quickly fund users\n // @param _value Amount of token to be created\n function mint(uint256 _value) external returns (bool) {\n _mint(msg.sender, _value);\n return true;\n }\n\n //\n // Burn methods\n //\n\n // @dev Burns tokens belonging to the sender\n // @param _value Amount of token to be burned\n function burn(uint256 _value) public onlyOwner {\n // TODO: add a function & modifier to enable for all accounts without doing\n // a contract migration?\n super.burn(_value);\n }\n\n // @dev Burns tokens belonging to the specified address\n // @param _who The account whose tokens we're burning\n // @param _value Amount of token to be burned\n function burn(address _who, uint256 _value) public onlyOwner {\n _burn(_who, _value);\n }\n\n //\n // approveAndCall methods\n //\n\n // @dev Add spender to whitelist of spenders for approveAndCall\n // @param _spender Address to add\n function addCallSpenderWhitelist(address _spender) public onlyOwner {\n callSpenderWhitelist[_spender] = true;\n emit AddCallSpenderWhitelist(msg.sender, _spender);\n }\n\n // @dev Remove spender from whitelist of spenders for approveAndCall\n // @param _spender Address to remove\n function removeCallSpenderWhitelist(address _spender) public onlyOwner {\n delete callSpenderWhitelist[_spender];\n emit RemoveCallSpenderWhitelist(msg.sender, _spender);\n }\n\n // @dev Approve transfer of tokens and make a contract call in a single\n // @dev transaction. This allows a DApp to avoid requiring two MetaMask\n // @dev approvals for a single logical action, such as creating a listing,\n // @dev which requires the seller to approve a token transfer and the\n // @dev marketplace contract to transfer tokens from the seller.\n //\n // @dev This is based on the ERC827 function approveAndCall and avoids\n // @dev security issues by only working with a whitelisted set of _spender\n // @dev addresses. The other difference is that the combination of this\n // @dev function ensures that the proxied function call receives the\n // @dev msg.sender for this function as its first parameter.\n //\n // @param _spender The address that will spend the funds.\n // @param _value The amount of tokens to be spent.\n // @param _selector Function selector for function to be called.\n // @param _callParams Packed, encoded parameters, omitting the first parameter which is always msg.sender\n function approveAndCallWithSender(\n address _spender,\n uint256 _value,\n bytes4 _selector,\n bytes memory _callParams\n ) public payable returns (bool) {\n require(_spender != address(this), \"token contract can't be approved\");\n require(callSpenderWhitelist[_spender], \"spender not in whitelist\");\n\n require(super.approve(_spender, _value), \"approve failed\");\n\n bytes memory callData = abi.encodePacked(\n _selector,\n uint256(msg.sender),\n _callParams\n );\n // solium-disable-next-line security/no-call-value\n (bool success, ) = _spender.call.value(msg.value)(callData);\n require(success, \"proxied call failed\");\n return true;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\ncontract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev See {ERC20-_burnFrom}.\n */\n function burnFrom(address account, uint256 amount) public {\n _burnFrom(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./ERC20.sol\";\nimport \"../../access/roles/MinterRole.sol\";\n\n/**\n * @dev Extension of {ERC20} that adds a set of accounts with the {MinterRole},\n * which have permission to mint (create) new tokens as they see fit.\n *\n * At construction, the deployer of the contract is the only minter.\n */\ncontract ERC20Mintable is ERC20, MinterRole {\n /**\n * @dev See {ERC20-_mint}.\n *\n * Requirements:\n *\n * - the caller must have the {MinterRole}.\n */\n function mint(address account, uint256 amount) public onlyMinter returns (bool) {\n _mint(account, amount);\n return true;\n }\n}\n" + }, + "contracts/mocks/WhitelistedPausableToken.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol\";\n\n/**\n * @title Contract for enforcing a list of addresses allowed to send or receive tokens\n * @dev Until the whitelist expiration expires, this contract only permits\n * token transfers in which an allowed transactor is either the sender or\n * recipient. Once the whitelist expiration passes, it becomes impossible to\n * re-enable the whitelist.\n *\n * This contract inherits from ERC20Pausable to enforce both pausing and\n * whitelists for transfer calls.\n */\ncontract WhitelistedPausableToken is ERC20Pausable {\n address public owner = msg.sender;\n\n // UNIX timestamp (in seconds) after which this whitelist no longer applies\n uint256 public whitelistExpiration;\n // While the whitelist is active, either the sender or recipient must be\n // in allowedTransactors.\n mapping(address => bool) public allowedTransactors;\n\n event SetWhitelistExpiration(uint256 expiration);\n event AllowedTransactorAdded(address sender);\n event AllowedTransactorRemoved(address sender);\n\n //\n // Functions for maintaining whitelist\n //\n\n modifier onlyOwner {\n require(msg.sender == owner);\n _;\n }\n modifier allowedTransfer(address _from, address _to) {\n require(\n // solium-disable-next-line operator-whitespace\n !whitelistActive() ||\n allowedTransactors[_from] ||\n allowedTransactors[_to],\n \"neither sender nor recipient are allowed\"\n );\n _;\n }\n\n function whitelistActive() public view returns (bool) {\n return block.timestamp < whitelistExpiration;\n }\n\n function addAllowedTransactor(address _transactor) public onlyOwner {\n emit AllowedTransactorAdded(_transactor);\n allowedTransactors[_transactor] = true;\n }\n\n function removeAllowedTransactor(address _transactor) public onlyOwner {\n emit AllowedTransactorRemoved(_transactor);\n delete allowedTransactors[_transactor];\n }\n\n /**\n * @dev Set the whitelist expiration, after which the whitelist no longer\n * applies.\n */\n function setWhitelistExpiration(uint256 _expiration) public onlyOwner {\n // allow only if whitelist expiration hasn't yet been set, or if the\n // whitelist expiration hasn't passed yet\n require(\n whitelistExpiration == 0 || whitelistActive(),\n \"an expired whitelist cannot be extended\"\n );\n // prevent possible mistakes in calling this function\n require(\n _expiration >= block.timestamp + 1 days,\n \"whitelist expiration not far enough into the future\"\n );\n emit SetWhitelistExpiration(_expiration);\n whitelistExpiration = _expiration;\n }\n\n //\n // ERC20 transfer functions that have been overridden to enforce the\n // whitelist.\n //\n\n function transfer(address _to, uint256 _value)\n public\n allowedTransfer(msg.sender, _to)\n returns (bool)\n {\n return super.transfer(_to, _value);\n }\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) public allowedTransfer(_from, _to) returns (bool) {\n return super.transferFrom(_from, _to, _value);\n }\n}\n" + }, + "@openzeppelin/contracts/GSN/Context.sol": { + "content": "pragma solidity ^0.5.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 GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\ncontract Context {\n // Empty internal constructor, to prevent people from mistakenly deploying\n // an instance of this contract, which should be used via inheritance.\n constructor () internal { }\n // solhint-disable-previous-line no-empty-blocks\n\n function _msgSender() internal view returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.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 {ERC20Mintable}.\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 guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 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 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20};\n *\n * Requirements:\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for `sender`'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\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 returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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 returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(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 {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.\n *\n * This is 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(address owner, address spender, uint256 amount) internal {\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 Destroys `amount` tokens from `account`.`amount` is then deducted\n * from the caller's allowance.\n *\n * See {_burn} and {_approve}.\n */\n function _burnFrom(address account, uint256 amount) internal {\n _burn(account, amount);\n _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, \"ERC20: burn amount exceeds allowance\"));\n }\n}\n" + }, + "@openzeppelin/contracts/access/roles/MinterRole.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"../Roles.sol\";\n\ncontract MinterRole is Context {\n using Roles for Roles.Role;\n\n event MinterAdded(address indexed account);\n event MinterRemoved(address indexed account);\n\n Roles.Role private _minters;\n\n constructor () internal {\n _addMinter(_msgSender());\n }\n\n modifier onlyMinter() {\n require(isMinter(_msgSender()), \"MinterRole: caller does not have the Minter role\");\n _;\n }\n\n function isMinter(address account) public view returns (bool) {\n return _minters.has(account);\n }\n\n function addMinter(address account) public onlyMinter {\n _addMinter(account);\n }\n\n function renounceMinter() public {\n _removeMinter(_msgSender());\n }\n\n function _addMinter(address account) internal {\n _minters.add(account);\n emit MinterAdded(account);\n }\n\n function _removeMinter(address account) internal {\n _minters.remove(account);\n emit MinterRemoved(account);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Roles.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @title Roles\n * @dev Library for managing addresses assigned to a Role.\n */\nlibrary Roles {\n struct Role {\n mapping (address => bool) bearer;\n }\n\n /**\n * @dev Give an account access to this role.\n */\n function add(Role storage role, address account) internal {\n require(!has(role, account), \"Roles: account already has role\");\n role.bearer[account] = true;\n }\n\n /**\n * @dev Remove an account's access to this role.\n */\n function remove(Role storage role, address account) internal {\n require(has(role, account), \"Roles: account does not have role\");\n role.bearer[account] = false;\n }\n\n /**\n * @dev Check if an account has this role.\n * @return bool\n */\n function has(Role storage role, address account) internal view returns (bool) {\n require(account != address(0), \"Roles: account is the zero address\");\n return role.bearer[account];\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20Pausable.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./ERC20.sol\";\nimport \"../../lifecycle/Pausable.sol\";\n\n/**\n * @title Pausable token\n * @dev ERC20 with pausable transfers and allowances.\n *\n * Useful if you want to stop trades until the end of a crowdsale, or have\n * an emergency switch for freezing all token transfers in the event of a large\n * bug.\n */\ncontract ERC20Pausable is ERC20, Pausable {\n function transfer(address to, uint256 value) public whenNotPaused returns (bool) {\n return super.transfer(to, value);\n }\n\n function transferFrom(address from, address to, uint256 value) public whenNotPaused returns (bool) {\n return super.transferFrom(from, to, value);\n }\n\n function approve(address spender, uint256 value) public whenNotPaused returns (bool) {\n return super.approve(spender, value);\n }\n\n function increaseAllowance(address spender, uint256 addedValue) public whenNotPaused returns (bool) {\n return super.increaseAllowance(spender, addedValue);\n }\n\n function decreaseAllowance(address spender, uint256 subtractedValue) public whenNotPaused returns (bool) {\n return super.decreaseAllowance(spender, subtractedValue);\n }\n}\n" + }, + "@openzeppelin/contracts/lifecycle/Pausable.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../GSN/Context.sol\";\nimport \"../access/roles/PauserRole.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\ncontract Pausable is Context, PauserRole {\n /**\n * @dev Emitted when the pause is triggered by a pauser (`account`).\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by a pauser (`account`).\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state. Assigns the Pauser role\n * to the deployer.\n */\n constructor () internal {\n _paused = false;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n */\n modifier whenNotPaused() {\n require(!_paused, \"Pausable: paused\");\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n */\n modifier whenPaused() {\n require(_paused, \"Pausable: not paused\");\n _;\n }\n\n /**\n * @dev Called by a pauser to pause, triggers stopped state.\n */\n function pause() public onlyPauser whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Called by a pauser to unpause, returns to normal state.\n */\n function unpause() public onlyPauser whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n}\n" + }, + "@openzeppelin/contracts/access/roles/PauserRole.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"../Roles.sol\";\n\ncontract PauserRole is Context {\n using Roles for Roles.Role;\n\n event PauserAdded(address indexed account);\n event PauserRemoved(address indexed account);\n\n Roles.Role private _pausers;\n\n constructor () internal {\n _addPauser(_msgSender());\n }\n\n modifier onlyPauser() {\n require(isPauser(_msgSender()), \"PauserRole: caller does not have the Pauser role\");\n _;\n }\n\n function isPauser(address account) public view returns (bool) {\n return _pausers.has(account);\n }\n\n function addPauser(address account) public onlyPauser {\n _addPauser(account);\n }\n\n function renouncePauser() public {\n _removePauser(_msgSender());\n }\n\n function _addPauser(address account) internal {\n _pausers.add(account);\n emit PauserAdded(account);\n }\n\n function _removePauser(address account) internal {\n _pausers.remove(account);\n emit PauserRemoved(account);\n }\n}\n" + }, + "contracts/mocks/MockCToken.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n IERC20,\n ERC20,\n ERC20Mintable\n} from \"@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol\";\nimport {\n ERC20Detailed\n} from \"@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\";\n\nimport { ICERC20 } from \"../strategies/ICompound.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\n\ncontract MockCToken is ICERC20, ERC20, ERC20Detailed, ERC20Mintable {\n using StableMath for uint256;\n\n IERC20 public underlyingToken;\n // underlying = cToken * exchangeRate\n // cToken = underlying / exchangeRate\n uint256 exchangeRate;\n address public comptroller;\n\n constructor(ERC20Detailed _underlyingToken, address _comptroller)\n public\n ERC20Detailed(\"cMock\", \"cMK\", 8)\n {\n uint8 underlyingDecimals = _underlyingToken.decimals();\n // if has 18 dp, exchange rate should be 1e26\n // if has 8 dp, exchange rate should be 1e18\n if (underlyingDecimals > 8) {\n exchangeRate = 10**uint256(18 + underlyingDecimals - 10);\n } else if (underlyingDecimals < 8) {\n // e.g. 18-8+6 = 16\n exchangeRate = 10**uint256(18 - 8 + underlyingDecimals);\n } else {\n exchangeRate = 1e18;\n }\n underlyingToken = _underlyingToken;\n comptroller = _comptroller;\n }\n\n function mint(uint256 mintAmount) external returns (uint256) {\n // Credit them with cToken\n _mint(msg.sender, mintAmount.divPrecisely(exchangeRate));\n // Take their reserve\n underlyingToken.transferFrom(msg.sender, address(this), mintAmount);\n return 0;\n }\n\n function redeem(uint256 redeemAmount) external returns (uint256) {\n uint256 tokenAmount = redeemAmount.mulTruncate(exchangeRate);\n // Burn the cToken\n _burn(msg.sender, redeemAmount);\n // Transfer underlying to caller\n underlyingToken.transfer(msg.sender, tokenAmount);\n return 0;\n }\n\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256) {\n uint256 cTokens = redeemAmount.divPrecisely(exchangeRate);\n // Burn the cToken\n _burn(msg.sender, cTokens);\n // Transfer underlying to caller\n underlyingToken.transfer(msg.sender, redeemAmount);\n return 0;\n }\n\n function balanceOfUnderlying(address owner) external returns (uint256) {\n uint256 cTokenBal = this.balanceOf(owner);\n return cTokenBal.mulTruncate(exchangeRate);\n }\n\n function updateExchangeRate() internal returns (uint256) {\n uint256 factor = 100002 * (10**13); // 0.002%\n exchangeRate = exchangeRate.mulTruncate(factor);\n }\n\n function exchangeRateStored() external view returns (uint256) {\n return exchangeRate;\n }\n\n function supplyRatePerBlock() external view returns (uint256) {\n return 141 * (10**8);\n }\n}\n" + }, + "contracts/strategies/ICompound.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @dev Compound C Token interface\n * Documentation: https://compound.finance/developers/ctokens\n */\ninterface ICERC20 {\n /**\n * @notice The mint function transfers an asset into the protocol, which begins accumulating\n * interest based on the current Supply Rate for the asset. The user receives a quantity of\n * cTokens equal to the underlying tokens supplied, divided by the current Exchange Rate.\n * @param mintAmount The amount of the asset to be supplied, in units of the underlying asset.\n * @return 0 on success, otherwise an Error codes\n */\n function mint(uint256 mintAmount) external returns (uint256);\n\n /**\n * @notice Sender redeems cTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of cTokens to redeem into underlying\n * @return uint 0=success, otherwise an error code.\n */\n function redeem(uint256 redeemTokens) external returns (uint256);\n\n /**\n * @notice The redeem underlying function converts cTokens into a specified quantity of the underlying\n * asset, and returns them to the user. The amount of cTokens redeemed is equal to the quantity of\n * underlying tokens received, divided by the current Exchange Rate. The amount redeemed must be less\n * than the user's Account Liquidity and the market's available liquidity.\n * @param redeemAmount The amount of underlying to be redeemed.\n * @return 0 on success, otherwise an error code.\n */\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256);\n\n /**\n * @notice The user's underlying balance, representing their assets in the protocol, is equal to\n * the user's cToken balance multiplied by the Exchange Rate.\n * @param owner The account to get the underlying balance of.\n * @return The amount of underlying currently owned by the account.\n */\n function balanceOfUnderlying(address owner) external returns (uint256);\n\n /**\n * @notice Calculates the exchange rate from the underlying to the CToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() external view returns (uint256);\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view returns (uint256);\n\n /**\n * @notice Get the supply rate per block for supplying the token to Compound.\n */\n function supplyRatePerBlock() external view returns (uint256);\n\n /**\n * @notice Address of the Compound Comptroller.\n */\n function comptroller() external view returns (address);\n}\n" + }, + "contracts/strategies/CompoundStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Compound Strategy\n * @notice Investment strategy for investing stablecoins via Compound\n * @author Origin Protocol Inc\n */\nimport { ICERC20 } from \"./ICompound.sol\";\nimport { IComptroller } from \"../interfaces/IComptroller.sol\";\nimport {\n IERC20,\n InitializableAbstractStrategy\n} from \"../utils/InitializableAbstractStrategy.sol\";\n\ncontract CompoundStrategy is InitializableAbstractStrategy {\n event SkippedWithdrawal(address asset, uint256 amount);\n\n /**\n * @dev Collect accumulated COMP and send to Vault.\n */\n function collectRewardToken() external onlyVault nonReentrant {\n // Claim COMP from Comptroller\n ICERC20 cToken = _getCTokenFor(assetsMapped[0]);\n IComptroller comptroller = IComptroller(cToken.comptroller());\n comptroller.claimComp(address(this));\n // Transfer COMP to Vault\n IERC20 rewardToken = IERC20(rewardTokenAddress);\n uint256 balance = rewardToken.balanceOf(address(this));\n emit RewardTokenCollected(vaultAddress, balance);\n rewardToken.safeTransfer(vaultAddress, balance);\n }\n\n /**\n * @dev Deposit asset into Compound\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n * @return amountDeposited Amount of asset that was deposited\n */\n function deposit(address _asset, uint256 _amount)\n external\n onlyVault\n nonReentrant\n {\n _deposit(_asset, _amount);\n }\n\n /**\n * @dev Deposit asset into Compound\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n * @return amountDeposited Amount of asset that was deposited\n */\n function _deposit(address _asset, uint256 _amount) internal {\n require(_amount > 0, \"Must deposit something\");\n ICERC20 cToken = _getCTokenFor(_asset);\n emit Deposit(_asset, address(cToken), _amount);\n require(cToken.mint(_amount) == 0, \"cToken mint failed\");\n }\n\n /**\n * @dev Deposit the entire balance of any supported asset into Compound\n */\n function depositAll() external onlyVault nonReentrant {\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n uint256 balance = IERC20(assetsMapped[i]).balanceOf(address(this));\n if (balance > 0) {\n _deposit(assetsMapped[i], balance);\n }\n }\n }\n\n /**\n * @dev Withdraw asset from Compound\n * @param _recipient Address to receive withdrawn asset\n * @param _asset Address of asset to withdraw\n * @param _amount Amount of asset to withdraw\n * @return amountWithdrawn Amount of asset that was withdrawn\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external onlyVault nonReentrant {\n require(_amount > 0, \"Must withdraw something\");\n require(_recipient != address(0), \"Must specify recipient\");\n\n ICERC20 cToken = _getCTokenFor(_asset);\n // If redeeming 0 cTokens, just skip, else COMP will revert\n uint256 cTokensToRedeem = _convertUnderlyingToCToken(cToken, _amount);\n if (cTokensToRedeem == 0) {\n emit SkippedWithdrawal(_asset, _amount);\n return;\n }\n\n emit Withdrawal(_asset, address(cToken), _amount);\n require(cToken.redeemUnderlying(_amount) == 0, \"Redeem failed\");\n IERC20(_asset).safeTransfer(_recipient, _amount);\n }\n\n /**\n * @dev Remove all assets from platform and send them to Vault contract.\n */\n function withdrawAll() external onlyVaultOrGovernor nonReentrant {\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n // Redeem entire balance of cToken\n ICERC20 cToken = _getCTokenFor(assetsMapped[i]);\n if (cToken.balanceOf(address(this)) > 0) {\n require(\n cToken.redeem(cToken.balanceOf(address(this))) == 0,\n \"Redeem failed\"\n );\n // Transfer entire balance to Vault\n IERC20 asset = IERC20(assetsMapped[i]);\n asset.safeTransfer(\n vaultAddress,\n asset.balanceOf(address(this))\n );\n }\n }\n }\n\n /**\n * @dev Get the total asset value held in the platform\n * This includes any interest that was generated since depositing\n * Compound exchange rate between the cToken and asset gradually increases,\n * causing the cToken to be worth more corresponding asset.\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance)\n {\n // Balance is always with token cToken decimals\n ICERC20 cToken = _getCTokenFor(_asset);\n balance = _checkBalance(cToken);\n }\n\n /**\n * @dev Get the total asset value held in the platform\n * underlying = (cTokenAmt * exchangeRate) / 1e18\n * @param _cToken cToken for which to check balance\n * @return balance Total value of the asset in the platform\n */\n function _checkBalance(ICERC20 _cToken)\n internal\n view\n returns (uint256 balance)\n {\n uint256 cTokenBalance = _cToken.balanceOf(address(this));\n uint256 exchangeRate = _cToken.exchangeRateStored();\n // e.g. 50e8*205316390724364402565641705 / 1e18 = 1.0265..e18\n balance = cTokenBalance.mul(exchangeRate).div(1e18);\n }\n\n /**\n * @dev Retuns bool indicating whether asset is supported by strategy\n * @param _asset Address of the asset\n */\n function supportsAsset(address _asset) external view returns (bool) {\n return assetToPToken[_asset] != address(0);\n }\n\n /**\n * @dev Approve the spending of all assets by their corresponding cToken,\n * if for some reason is it necessary.\n */\n function safeApproveAllTokens() external {\n uint256 assetCount = assetsMapped.length;\n for (uint256 i = 0; i < assetCount; i++) {\n address asset = assetsMapped[i];\n address cToken = assetToPToken[asset];\n // Safe approval\n IERC20(asset).safeApprove(cToken, 0);\n IERC20(asset).safeApprove(cToken, uint256(-1));\n }\n }\n\n /**\n * @dev Internal method to respond to the addition of new asset / cTokens\n * We need to approve the cToken and give it permission to spend the asset\n * @param _asset Address of the asset to approve\n * @param _cToken This cToken has the approval approval\n */\n function _abstractSetPToken(address _asset, address _cToken) internal {\n // Safe approval\n IERC20(_asset).safeApprove(_cToken, 0);\n IERC20(_asset).safeApprove(_cToken, uint256(-1));\n }\n\n /**\n * @dev Get the cToken wrapped in the ICERC20 interface for this asset.\n * Fails if the pToken doesn't exist in our mappings.\n * @param _asset Address of the asset\n * @return Corresponding cToken to this asset\n */\n function _getCTokenFor(address _asset) internal view returns (ICERC20) {\n address cToken = assetToPToken[_asset];\n require(cToken != address(0), \"cToken does not exist\");\n return ICERC20(cToken);\n }\n\n /**\n * @dev Converts an underlying amount into cToken amount\n * cTokenAmt = (underlying * 1e18) / exchangeRate\n * @param _cToken cToken for which to change\n * @param _underlying Amount of underlying to convert\n * @return amount Equivalent amount of cTokens\n */\n function _convertUnderlyingToCToken(ICERC20 _cToken, uint256 _underlying)\n internal\n view\n returns (uint256 amount)\n {\n uint256 exchangeRate = _cToken.exchangeRateStored();\n // e.g. 1e18*1e18 / 205316390724364402565641705 = 50e8\n // e.g. 1e8*1e18 / 205316390724364402565641705 = 0.45 or 0\n amount = _underlying.mul(1e18).div(exchangeRate);\n }\n}\n" + }, + "contracts/interfaces/IComptroller.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IComptroller {\n /**\n * @notice Claim all the comp accrued by holder in all markets\n * @param holder The address to claim COMP for\n */\n function claimComp(address holder) external;\n}\n" + }, + "contracts/mocks/MockAave.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n IAaveAToken,\n IAaveLendingPool,\n ILendingPoolAddressesProvider\n} from \"../strategies/IAave.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport {\n IERC20,\n ERC20,\n ERC20Mintable\n} from \"@openzeppelin/contracts/token/ERC20/ERC20Mintable.sol\";\nimport {\n ERC20Detailed\n} from \"@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol\";\n\n// 1. User calls 'getLendingPool'\n// 2. User calls 'deposit' (Aave)\n// - Deposit their underlying\n// - Mint aToken to them\n// 3. User calls redeem (aToken)\n// - Retrieve their aToken\n// - Return equal amount of underlying\n\ncontract MockAToken is ERC20Mintable, ERC20Detailed {\n address public lendingPool;\n IERC20 public underlyingToken;\n using SafeERC20 for IERC20;\n\n constructor(\n address _lendingPool,\n string memory _name,\n string memory _symbol,\n IERC20 _underlyingToken\n )\n public\n ERC20Detailed(\n _name,\n _symbol,\n ERC20Detailed(address(_underlyingToken)).decimals()\n )\n {\n lendingPool = _lendingPool;\n underlyingToken = _underlyingToken;\n addMinter(_lendingPool);\n }\n\n function redeem(uint256 _amount) external {\n // Redeem these a Tokens\n _burn(msg.sender, _amount);\n // For the underlying\n underlyingToken.safeTransferFrom(lendingPool, msg.sender, _amount);\n }\n}\n\ncontract MockAave is IAaveLendingPool, ILendingPoolAddressesProvider {\n using SafeERC20 for IERC20;\n using StableMath for uint256;\n\n mapping(address => address) reserveToAToken;\n address pool = address(this);\n address payable core = address(uint160(address(this)));\n uint256 factor;\n\n function addAToken(address _aToken, address _underlying) public {\n IERC20(_underlying).safeApprove(_aToken, 0);\n IERC20(_underlying).safeApprove(_aToken, uint256(-1));\n reserveToAToken[_underlying] = _aToken;\n }\n\n // set the reserve factor / basically the interest on deposit\n // in 18 precision\n // so 0.5% would be 5 * 10 ^ 15\n function setFactor(uint256 factor_) public {\n factor = factor_;\n }\n\n function deposit(\n address _reserve,\n uint256 _amount,\n uint16 /*_referralCode*/\n ) external {\n uint256 previousBal = IERC20(reserveToAToken[_reserve]).balanceOf(\n msg.sender\n );\n uint256 interest = previousBal.mulTruncate(factor);\n ERC20Mintable(reserveToAToken[_reserve]).mint(msg.sender, interest);\n // Take their reserve\n IERC20(_reserve).safeTransferFrom(msg.sender, address(this), _amount);\n // Credit them with aToken\n ERC20Mintable(reserveToAToken[_reserve]).mint(msg.sender, _amount);\n }\n\n function getLendingPool() external view returns (address) {\n return pool;\n }\n\n function getLendingPoolCore() external view returns (address payable) {\n return core;\n }\n}\n" + }, + "contracts/strategies/IAave.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @dev Interface for Aaves A Token\n * Documentation: https://developers.aave.com/#atokens\n */\ninterface IAaveAToken {\n /**\n * @notice Non-standard ERC20 function to redeem an _amount of aTokens for the underlying\n * asset, burning the aTokens during the process.\n * @param _amount Amount of aTokens\n */\n function redeem(uint256 _amount) external;\n\n /**\n * @notice returns the current total aToken balance of _user all interest collected included.\n * To obtain the user asset principal balance with interests excluded , ERC20 non-standard\n * method principalBalanceOf() can be used.\n */\n function balanceOf(address _user) external view returns (uint256);\n}\n\n/**\n * @dev Interface for Aaves Lending Pool\n * Documentation: https://developers.aave.com/#lendingpool\n */\ninterface IAaveLendingPool {\n /**\n * @notice Deposits a certain _amount of an asset specified by the _reserve parameter.\n * @dev The caller receives a certain amount of corresponding aTokens in exchange.\n * The amount of aTokens received depends on the corresponding aToken exchange rate.\n * LendingPoolCore must be approved to spend this reserve\n */\n function deposit(\n address _reserve,\n uint256 _amount,\n uint16 _referralCode\n ) external;\n}\n\n/**\n * @dev Interface for Aaves Lending Pool\n * Documentation: https://developers.aave.com/#lendingpooladdressesprovider\n */\ninterface ILendingPoolAddressesProvider {\n /**\n * @notice Get the current address for Aave LendingPool\n * @dev Lending pool is the core contract on which to call deposit\n */\n function getLendingPool() external view returns (address);\n\n /**\n * @notice Get the address for lendingPoolCore\n * @dev IMPORTANT - this is where _reserve must be approved before deposit\n */\n function getLendingPoolCore() external view returns (address payable);\n}\n" + }, + "contracts/strategies/AaveStrategy.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Aave Strategy\n * @notice Investment strategy for investing stablecoins via Aave\n * @author Origin Protocol Inc\n */\nimport \"./IAave.sol\";\nimport {\n IERC20,\n InitializableAbstractStrategy\n} from \"../utils/InitializableAbstractStrategy.sol\";\n\ncontract AaveStrategy is InitializableAbstractStrategy {\n uint16 constant referralCode = 92;\n\n /**\n * @dev Deposit asset into Aave\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n * @return amountDeposited Amount of asset that was deposited\n */\n function deposit(address _asset, uint256 _amount)\n external\n onlyVault\n nonReentrant\n {\n _deposit(_asset, _amount);\n }\n\n /**\n * @dev Deposit asset into Aave\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n * @return amountDeposited Amount of asset that was deposited\n */\n function _deposit(address _asset, uint256 _amount) internal {\n require(_amount > 0, \"Must deposit something\");\n IAaveAToken aToken = _getATokenFor(_asset);\n emit Deposit(_asset, address(aToken), _amount);\n _getLendingPool().deposit(_asset, _amount, referralCode);\n }\n\n /**\n * @dev Deposit the entire balance of any supported asset into Aave\n */\n function depositAll() external onlyVault nonReentrant {\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n uint256 balance = IERC20(assetsMapped[i]).balanceOf(address(this));\n if (balance > 0) {\n _deposit(assetsMapped[i], balance);\n }\n }\n }\n\n /**\n * @dev Withdraw asset from Aave\n * @param _recipient Address to receive withdrawn asset\n * @param _asset Address of asset to withdraw\n * @param _amount Amount of asset to withdraw\n * @return amountWithdrawn Amount of asset that was withdrawn\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external onlyVault nonReentrant {\n require(_amount > 0, \"Must withdraw something\");\n require(_recipient != address(0), \"Must specify recipient\");\n\n IAaveAToken aToken = _getATokenFor(_asset);\n emit Withdrawal(_asset, address(aToken), _amount);\n aToken.redeem(_amount);\n IERC20(_asset).safeTransfer(_recipient, _amount);\n }\n\n /**\n * @dev Remove all assets from platform and send them to Vault contract.\n */\n function withdrawAll() external onlyVaultOrGovernor nonReentrant {\n for (uint256 i = 0; i < assetsMapped.length; i++) {\n // Redeem entire balance of aToken\n IAaveAToken aToken = _getATokenFor(assetsMapped[i]);\n uint256 balance = aToken.balanceOf(address(this));\n if (balance > 0) {\n aToken.redeem(balance);\n // Transfer entire balance to Vault\n IERC20 asset = IERC20(assetsMapped[i]);\n asset.safeTransfer(\n vaultAddress,\n asset.balanceOf(address(this))\n );\n }\n }\n }\n\n /**\n * @dev Get the total asset value held in the platform\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance)\n {\n // Balance is always with token aToken decimals\n IAaveAToken aToken = _getATokenFor(_asset);\n balance = aToken.balanceOf(address(this));\n }\n\n /**\n * @dev Retuns bool indicating whether asset is supported by strategy\n * @param _asset Address of the asset\n */\n function supportsAsset(address _asset) external view returns (bool) {\n return assetToPToken[_asset] != address(0);\n }\n\n /**\n * @dev Approve the spending of all assets by their corresponding aToken,\n * if for some reason is it necessary.\n */\n function safeApproveAllTokens() external onlyGovernor nonReentrant {\n uint256 assetCount = assetsMapped.length;\n address lendingPoolVault = _getLendingPoolCore();\n // approve the pool to spend the bAsset\n for (uint256 i = 0; i < assetCount; i++) {\n address asset = assetsMapped[i];\n // Safe approval\n IERC20(asset).safeApprove(lendingPoolVault, 0);\n IERC20(asset).safeApprove(lendingPoolVault, uint256(-1));\n }\n }\n\n /**\n * @dev Internal method to respond to the addition of new asset / aTokens\n * We need to approve the aToken and give it permission to spend the asset\n * @param _asset Address of the asset to approve\n * @param _aToken This aToken has the approval approval\n */\n function _abstractSetPToken(address _asset, address _aToken) internal {\n address lendingPoolVault = _getLendingPoolCore();\n IERC20(_asset).safeApprove(lendingPoolVault, 0);\n IERC20(_asset).safeApprove(lendingPoolVault, uint256(-1));\n }\n\n /**\n * @dev Get the aToken wrapped in the ICERC20 interface for this asset.\n * Fails if the pToken doesn't exist in our mappings.\n * @param _asset Address of the asset\n * @return Corresponding aToken to this asset\n */\n function _getATokenFor(address _asset) internal view returns (IAaveAToken) {\n address aToken = assetToPToken[_asset];\n require(aToken != address(0), \"aToken does not exist\");\n return IAaveAToken(aToken);\n }\n\n /**\n * @dev Get the current address of the Aave lending pool, which is the gateway to\n * depositing.\n * @return Current lending pool implementation\n */\n function _getLendingPool() internal view returns (IAaveLendingPool) {\n address lendingPool = ILendingPoolAddressesProvider(platformAddress)\n .getLendingPool();\n require(lendingPool != address(0), \"Lending pool does not exist\");\n return IAaveLendingPool(lendingPool);\n }\n\n /**\n * @dev Get the current address of the Aave lending pool core, which stores all the\n * reserve tokens in its vault.\n * @return Current lending pool core address\n */\n function _getLendingPoolCore() internal view returns (address payable) {\n address payable lendingPoolCore = ILendingPoolAddressesProvider(\n platformAddress\n )\n .getLendingPoolCore();\n require(\n lendingPoolCore != address(uint160(address(0))),\n \"Lending pool core does not exist\"\n );\n return lendingPoolCore;\n }\n}\n" + }, + "contracts/mocks/curve/MockCurvePool.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IMintableERC20 } from \"../MintableERC20.sol\";\nimport { ICurvePool } from \"../../strategies/ICurvePool.sol\";\nimport { StableMath } from \"../../utils/StableMath.sol\";\nimport \"../../utils/Helpers.sol\";\n\ncontract MockCurvePool is ERC20 {\n using StableMath for uint256;\n\n address[] public coins;\n address lpToken;\n\n constructor(address[3] memory _coins, address _lpToken) public {\n coins = _coins;\n lpToken = _lpToken;\n }\n\n // Returns the same amount of LP tokens in 1e18 decimals\n function add_liquidity(uint256[3] calldata _amounts, uint256 _minAmount)\n external\n {\n uint256 sum = 0;\n for (uint256 i = 0; i < _amounts.length; i++) {\n if (_amounts[i] > 0) {\n IERC20(coins[i]).transferFrom(\n msg.sender,\n address(this),\n _amounts[i]\n );\n uint256 assetDecimals = Helpers.getDecimals(coins[i]);\n // Convert to 1e18 and add to sum\n sum += _amounts[i].scaleBy(int8(18 - assetDecimals));\n }\n }\n // Hacky way of simulating slippage to check _minAmount\n if (sum == 29000e18) sum = 14500e18;\n require(sum >= _minAmount, \"Slippage ruined your day\");\n // Send LP token to sender, e.g. 3CRV\n IMintableERC20(lpToken).mint(sum);\n IERC20(lpToken).transfer(msg.sender, sum);\n }\n\n // Dumb implementation that returns the same amount\n function calc_withdraw_one_coin(uint256 _amount, int128 _index)\n public\n view\n returns (uint256)\n {\n uint256 assetDecimals = Helpers.getDecimals(coins[uint256(_index)]);\n return _amount.scaleBy(int8(assetDecimals - 18));\n }\n\n function remove_liquidity_one_coin(\n uint256 _amount,\n int128 _index,\n uint256 _minAmount\n ) external {\n IERC20(lpToken).transferFrom(msg.sender, address(this), _amount);\n uint256[] memory amounts = new uint256[](coins.length);\n amounts[uint256(_index)] = _amount;\n uint256 amount = calc_withdraw_one_coin(_amount, _index);\n IERC20(coins[uint256(_index)]).transfer(msg.sender, amount);\n }\n\n function get_virtual_price() external view returns (uint256) {\n return 1 * 10**18;\n }\n\n function remove_liquidity(uint256 _amount, uint256[3] memory _min_amounts)\n public\n {\n IERC20(lpToken).transferFrom(msg.sender, address(this), _amount);\n uint256 totalSupply = IERC20(lpToken).totalSupply();\n for (uint256 i = 0; i < 3; i++) {\n uint256 amount = _amount.div(totalSupply).mul(\n IERC20(coins[i]).balanceOf(address(this))\n );\n IERC20(coins[i]).transfer(msg.sender, amount);\n }\n }\n}\n" + }, + "contracts/mocks/MintableERC20.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ninterface IMintableERC20 {\n function mint(uint256 value) external returns (bool);\n}\n\n/**\n * @title ERC20Mintable\n * @dev ERC20 minting logic\n */\ncontract MintableERC20 is IMintableERC20, ERC20 {\n /**\n * @dev Function to mint tokens\n * @param value The amount of tokens to mint.\n * @return A boolean that indicates if the operation was successful.\n */\n function mint(uint256 value) public returns (bool) {\n _mint(msg.sender, value);\n return true;\n }\n}\n" + }, + "contracts/mocks/MockWETH.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockWETH is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"WETH\";\n string public constant name = \"WETH\";\n}\n" + }, + "contracts/mocks/MockUSDT.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockUSDT is MintableERC20 {\n uint256 public constant decimals = 6;\n string public constant symbol = \"USDT\";\n string public constant name = \"USDT Coin\";\n}\n" + }, + "contracts/mocks/MockUSDC.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockUSDC is MintableERC20 {\n uint256 public constant decimals = 6;\n string public constant symbol = \"USDC\";\n string public constant name = \"USD Coin\";\n}\n" + }, + "contracts/mocks/MockTUSD.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockTUSD is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"TUSD\";\n string public constant name = \"TrueUSD\";\n}\n" + }, + "contracts/mocks/MockNonStandardToken.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\n/**\n * Mock token contract to simulate tokens that don't\n * throw/revert when a transfer/transferFrom call fails\n */\ncontract MockNonStandardToken is MintableERC20 {\n uint256 public constant decimals = 6;\n string public constant symbol = \"NonStandardToken\";\n string public constant name = \"NonStandardToken\";\n\n function transfer(address recipient, uint256 amount) public returns (bool) {\n if (balanceOf(msg.sender) < amount) {\n // Fail silently\n return false;\n }\n\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) public returns (bool) {\n if (balanceOf(sender) < amount) {\n // Fail silently\n return false;\n }\n\n _transfer(sender, recipient, amount);\n _approve(\n sender,\n _msgSender(),\n allowance(sender, _msgSender()).sub(\n amount,\n \"ERC20: transfer amount exceeds allowance\"\n )\n );\n return true;\n }\n}\n" + }, + "contracts/mocks/MockMintableUniswapPair.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\nimport \"./MockUniswapPair.sol\";\n\ncontract MockMintableUniswapPair is MockUniswapPair, MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"Uniswap V2\";\n string public constant name = \"UNI-V2\";\n\n constructor(\n address _token0,\n address _token1,\n uint112 _reserve0,\n uint112 _reserve1\n ) public MockUniswapPair(_token0, _token1, _reserve0, _reserve1) {}\n}\n" + }, + "contracts/mocks/MockUniswapPair.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IUniswapV2Pair } from \"../interfaces/uniswap/IUniswapV2Pair.sol\";\n\ncontract MockUniswapPair is IUniswapV2Pair {\n address tok0;\n address tok1;\n uint112 reserve0;\n uint112 reserve1;\n uint256 blockTimestampLast;\n\n bool public hasSynced = false;\n\n constructor(\n address _token0,\n address _token1,\n uint112 _reserve0,\n uint112 _reserve1\n ) public {\n tok0 = _token0;\n tok1 = _token1;\n reserve0 = _reserve0;\n reserve1 = _reserve1;\n blockTimestampLast = block.timestamp;\n }\n\n function token0() external view returns (address) {\n return tok0;\n }\n\n function token1() external view returns (address) {\n return tok1;\n }\n\n function getReserves()\n external\n view\n returns (\n uint112,\n uint112,\n uint32\n )\n {\n return (reserve0, reserve1, uint32(blockTimestampLast));\n }\n\n function setReserves(uint112 _reserve0, uint112 _reserve1) public {\n reserve0 = _reserve0;\n reserve1 = _reserve1;\n blockTimestampLast = block.timestamp;\n }\n\n // CAUTION This will not work if you setReserves multiple times over multiple different blocks because then it wouldn't be a continuous reserve factor over that blockTimestamp,\n // this assumes an even reserve ratio all the way through\n function price0CumulativeLast() external view returns (uint256) {\n return\n uint256(FixedPoint.fraction(reserve1, reserve0)._x) *\n blockTimestampLast;\n }\n\n function price1CumulativeLast() external view returns (uint256) {\n return\n uint256(FixedPoint.fraction(reserve0, reserve1)._x) *\n blockTimestampLast;\n }\n\n function sync() external {\n hasSynced = true;\n }\n\n function checkHasSynced() external view {\n require(hasSynced, \"Not synced\");\n }\n}\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 // returns a uq112x112 which represents the ratio of the numerator to the denominator\n // equivalent to encode(numerator).div(denominator)\n function fraction(uint112 numerator, uint112 denominator)\n internal\n pure\n returns (uq112x112 memory)\n {\n require(denominator > 0, \"FixedPoint: DIV_BY_ZERO\");\n return uq112x112((uint224(numerator) << 112) / denominator);\n }\n}\n" + }, + "contracts/interfaces/uniswap/IUniswapV2Pair.sol": { + "content": "pragma solidity 0.5.11;\n\ninterface IUniswapV2Pair {\n function token0() external view returns (address);\n\n function token1() external view returns (address);\n\n function getReserves()\n external\n view\n returns (\n uint112 reserve0,\n uint112 reserve1,\n uint32 blockTimestampLast\n );\n\n function price0CumulativeLast() external view returns (uint256);\n\n function price1CumulativeLast() external view returns (uint256);\n\n function sync() external;\n}\n" + }, + "contracts/mocks/MockEvilDAI.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\nimport { IVault } from \"../interfaces/IVault.sol\";\n\ncontract MockEvilDAI is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"DAI\";\n string public constant name = \"DAI\";\n address host;\n address realCoin;\n\n constructor(address _host, address _realCoin) public {\n host = _host;\n realCoin = _realCoin;\n }\n\n function transferFrom(\n address _from,\n address _to,\n uint256 _amount\n ) public returns (bool) {\n // call mint again!\n if (_amount != 69) {\n IVault(host).mint(address(this), 69, 0);\n }\n return true;\n }\n}\n" + }, + "contracts/mocks/MockDAI.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockDAI is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"DAI\";\n string public constant name = \"DAI\";\n}\n" + }, + "contracts/mocks/MockCOMP.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"./MintableERC20.sol\";\n\ncontract MockCOMP is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"COMP\";\n string public constant name = \"COMP\";\n}\n" + }, + "contracts/mocks/curve/MockCRVMinter.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { IMintableERC20 } from \"../MintableERC20.sol\";\n\ncontract MockCRVMinter {\n address crv;\n\n constructor(address _crv) public {\n crv = _crv;\n }\n\n function mint(address _address) external {\n uint256 amount = 2e18;\n IMintableERC20(crv).mint(amount);\n IERC20(crv).transfer(_address, amount);\n }\n}\n" + }, + "contracts/mocks/curve/MockCRV.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../MintableERC20.sol\";\n\ncontract MockCRV is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"CRV\";\n string public constant name = \"Curve DAO Token\";\n}\n" + }, + "contracts/mocks/curve/Mock3CRV.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../MintableERC20.sol\";\n\ncontract Mock3CRV is MintableERC20 {\n uint256 public constant decimals = 18;\n string public constant symbol = \"3Crv\";\n string public constant name = \"Curve.fi DAI/USDC/USDT\";\n\n function mint(address to, uint256 value) public returns (bool) {\n _mint(to, value);\n return true;\n }\n\n function burnFrom(address from, uint256 value) public returns (bool) {\n _burn(from, value);\n return true;\n }\n}\n" + }, + "contracts/mocks/curve/MockCurveGauge.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\nimport { ICurveGauge } from \"../../strategies/ICurveGauge.sol\";\n\ncontract MockCurveGauge is ICurveGauge {\n mapping(address => uint256) private _balances;\n address lpToken;\n\n constructor(address _lpToken) public {\n lpToken = _lpToken;\n }\n\n function balanceOf(address account) public view returns (uint256) {\n return _balances[account];\n }\n\n function deposit(uint256 _value, address _account) external {\n IERC20(lpToken).transferFrom(msg.sender, address(this), _value);\n _balances[_account] += _value;\n }\n\n function withdraw(uint256 _value) external {\n IERC20(lpToken).transfer(msg.sender, _value);\n _balances[msg.sender] -= _value;\n }\n}\n" + }, + "contracts/liquidity/LiquidityReward.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { StableMath } from \"../utils/StableMath.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\n//\n// LiquidityReward contract doles out reward for liquidity\n// base off of Sushiswap's MasterChef: https://github.com/sushiswap/sushiswap/blob/master/contracts/MasterChef.sol\n//\ncontract LiquidityReward is Initializable, Governable {\n using SafeMath for uint256;\n using StableMath for uint256;\n using SafeERC20 for IERC20;\n\n // Info of each user.\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n int256 rewardDebt; // Reward debt. See explanation below.\n //\n // We do some fancy math here. Basically, any point in time, the amount of Reward Tokens\n // entitled to a user but is pending to be distributed is:\n //\n // pending reward = (user.amount * pool.accRewardPerShare) - user.rewardDebt\n //\n // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:\n // 1. The pool's `accRewardPerShare` (and `lastRewardBlock`) 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` gets updated.\n //\n // NOTE: rewardDebt can go negative because we allow withdraws without claiming the reward\n // in that case we owe the account holder some reward.\n }\n\n // Info of each pool.\n struct PoolInfo {\n IERC20 lpToken; // Address of LP token contract.\n uint256 lastRewardBlock; // Last block number that Reward calculation occurs.\n uint256 accRewardPerShare; // Accumulated Reward per share in reward precision. See below.\n }\n\n // The Reward token\n IERC20 public reward;\n\n // Reward tokens created per block in 1e18 precision.\n uint256 public rewardPerBlock;\n\n // Info on the LP.\n PoolInfo public pool;\n // total Reward debt, useful to calculate if we have enough to pay out all rewards\n int256 public totalRewardDebt;\n // Info of each user that stakes LP tokens.\n mapping(address => UserInfo) public userInfo;\n // The block number when Liquidity rewards ends.\n uint256 public endBlock;\n\n event CampaignStarted(\n uint256 rewardRate,\n uint256 startBlock,\n uint256 endBlock\n );\n event CampaignStopped(uint256 endBlock);\n event Deposit(address indexed user, uint256 amount);\n event Withdraw(address indexed user, uint256 amount);\n event Claim(address indexed user, uint256 amount);\n\n /**\n * Initializer for setting up Liquidity Reward internal state.\n * @param _reward Address of the reward token(OGN)\n * @param _lpToken Address of the LP token(Uniswap Pair)\n */\n function initialize(IERC20 _reward, IERC20 _lpToken)\n external\n onlyGovernor\n initializer\n {\n reward = _reward;\n pool.lpToken = _lpToken;\n pool.lastRewardBlock = block.number;\n }\n\n /**\n * @dev start a new reward campaign.\n * This will calculate all rewards up to the current block at the old rate.\n * This ensures that we pay everyone at the promised rate before update to the new rate.\n * @param _rewardPerBlock Amount rewarded per block\n * @param _startBlock Block number that we want to start the rewards at (0 for current block)\n * @param _numBlocks number of blocks that the campaign should last\n */\n function startCampaign(\n uint256 _rewardPerBlock,\n uint256 _startBlock,\n uint256 _numBlocks\n ) external onlyGovernor {\n // Calculate up to the current block at the current rate for everyone.\n updatePool();\n\n // total Pending calculated at the current pool rate\n uint256 totalPending = subDebt(\n pool.accRewardPerShare.mulTruncate(\n pool.lpToken.balanceOf(address(this))\n ),\n totalRewardDebt\n );\n\n require(\n reward.balanceOf(address(this)) >=\n _rewardPerBlock.mul(_numBlocks).add(totalPending),\n \"startCampaign: insufficient rewards\"\n );\n\n uint256 startBlock = _startBlock;\n if (startBlock == 0) {\n // start block number isn't given so we start at the current\n startBlock = block.number;\n }\n require(\n startBlock >= block.number,\n \"startCampaign: _startBlock can't be in the past\"\n );\n endBlock = startBlock.add(_numBlocks);\n // we don't start accrue until the startBlock\n pool.lastRewardBlock = startBlock;\n // new blocks start at the new reward rate\n rewardPerBlock = _rewardPerBlock;\n emit CampaignStarted(rewardPerBlock, startBlock, endBlock);\n }\n\n function stopCampaign() external onlyGovernor {\n //calculate until current pool\n updatePool();\n //end the block here (the CampaignMultiplier will be zero)\n endBlock = block.number;\n emit CampaignStopped(endBlock);\n }\n\n function campaignActive() external view returns (bool) {\n return endBlock > block.number && block.number >= pool.lastRewardBlock;\n }\n\n function balanceOf(address _account) external view returns (uint256) {\n return userInfo[_account].amount;\n }\n\n /**\n * @dev calculate the number of blocks since we last updated\n * within start and end as constraints\n * @param _to Block number of the ending point.\n * @return multiplier Multiplier over the given _from to _to block.\n */\n function getCampaignMultiplier(uint256 _to)\n internal\n view\n returns (uint256)\n {\n uint256 from = pool.lastRewardBlock;\n if (from > endBlock) {\n return 0;\n } else {\n return (_to < endBlock ? _to : endBlock).sub(from);\n }\n }\n\n /**\n * @dev View function to see pending rewards for each account on frontend.\n * @param _user Address of the account we're looking up.\n * @return reward Total rewards owed to this account.\n */\n function pendingRewards(address _user) external view returns (uint256) {\n UserInfo storage user = userInfo[_user];\n return _pendingRewards(user);\n }\n\n function _pendingRewards(UserInfo storage user)\n internal\n view\n returns (uint256)\n {\n uint256 accRewardPerShare = pool.accRewardPerShare;\n if (block.number > pool.lastRewardBlock) {\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\n if (lpSupply != 0) {\n uint256 multiplier = getCampaignMultiplier(block.number);\n uint256 incReward = multiplier.mul(rewardPerBlock);\n accRewardPerShare = accRewardPerShare.add(\n incReward.divPrecisely(lpSupply)\n );\n }\n }\n return\n subDebt(\n user.amount.mulTruncate(accRewardPerShare),\n user.rewardDebt\n );\n }\n\n /**\n * @dev View function to see total outstanding rewards for the entire contract.\n * This is how much is owed when everyone pulls out.\n * @return reward Total rewards owed to everyone.\n */\n function totalOutstandingRewards() external view returns (uint256) {\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n uint256 multiplier = getCampaignMultiplier(block.number);\n uint256 incReward = multiplier.mul(rewardPerBlock);\n uint256 accRewardPerShare = pool.accRewardPerShare;\n accRewardPerShare = accRewardPerShare.add(\n incReward.divPrecisely(lpSupply)\n );\n return\n subDebt(\n accRewardPerShare.mulTruncate(lpSupply),\n totalRewardDebt\n );\n }\n // no supply or not even started\n return 0;\n }\n\n /**\n * @dev External call for updating the pool.\n */\n function doUpdatePool() external {\n // There should be no harm allowing anyone to call this function.\n // It just updates the latest accRewardPerShare for the pool.\n updatePool();\n }\n\n /**\n * @dev Update the Liquidity Pool reward multiplier.\n * This locks in the accRewardPerShare from the last update block number to now.\n * Will fail if we do not have enough to pay everyone.\n * Always call updatePool whenever the balance changes!\n */\n function updatePool() internal {\n if (\n block.number <= pool.lastRewardBlock ||\n endBlock <= pool.lastRewardBlock\n ) {\n return;\n }\n\n uint256 lpSupply = pool.lpToken.balanceOf(address(this));\n if (lpSupply == 0) {\n pool.lastRewardBlock = block.number;\n return;\n }\n\n uint256 incReward = getCampaignMultiplier(block.number).mul(\n rewardPerBlock\n );\n // we are of course assuming lpTokens are in 1e18 precision\n uint256 accRewardPerShare = pool.accRewardPerShare.add(\n incReward.divPrecisely(lpSupply)\n );\n\n pool.accRewardPerShare = accRewardPerShare;\n pool.lastRewardBlock = block.number;\n }\n\n /**\n * @dev Deposit LP tokens into contract, must be preapproved.\n * @param _amount Amount of LPToken to deposit.\n */\n function deposit(uint256 _amount) external {\n UserInfo storage user = userInfo[msg.sender];\n updatePool();\n if (_amount > 0) {\n user.amount = user.amount.add(_amount);\n // newDebt is equal to the change in amount * accRewardPerShare (note accRewardPerShare is historic)\n int256 newDebt = int256(\n _amount.mulTruncate(pool.accRewardPerShare)\n );\n user.rewardDebt += newDebt;\n totalRewardDebt += newDebt;\n emit Deposit(msg.sender, _amount);\n pool.lpToken.safeTransferFrom(\n address(msg.sender),\n address(this),\n _amount\n );\n }\n }\n\n /**\n * @dev Exit out of the contract completely, withdraw LP tokens and claim rewards\n */\n function exit() external {\n UserInfo storage user = userInfo[msg.sender];\n // withdraw everything\n _withdraw(user, user.amount, true);\n }\n\n /**\n * @dev Withdraw LP tokens from contract.\n * @param _amount Amount of LPToken to withdraw.\n * @param _claim Boolean do we want to claim our rewards or not\n */\n function withdraw(uint256 _amount, bool _claim) external {\n UserInfo storage user = userInfo[msg.sender];\n _withdraw(user, _amount, _claim);\n }\n\n function _withdraw(\n UserInfo storage user,\n uint256 _amount,\n bool _claim\n ) internal {\n require(user.amount >= _amount, \"withdraw: overflow\");\n updatePool();\n\n // newDebt is equal to the change in amount * accRewardPerShare (note accRewardPerShare is historic)\n int256 newDebt = -int256(_amount.mulTruncate(pool.accRewardPerShare));\n if (_claim) {\n //This is an optimization so we don't modify the storage variable twice\n uint256 pending = subDebt(\n user.amount.mulTruncate(pool.accRewardPerShare),\n user.rewardDebt\n );\n if (pending > 0) {\n reward.safeTransfer(msg.sender, pending);\n emit Claim(msg.sender, pending);\n }\n newDebt += int256(pending);\n }\n\n // actually make the changes to the amount and debt\n if (_amount > 0) {\n user.amount = user.amount.sub(_amount);\n pool.lpToken.safeTransfer(address(msg.sender), _amount);\n }\n user.rewardDebt += newDebt;\n totalRewardDebt += newDebt;\n emit Withdraw(msg.sender, _amount);\n }\n\n /**\n * @dev Claim all pending rewards up to current block\n */\n function claim() external {\n UserInfo storage user = userInfo[msg.sender];\n uint256 pending = _pendingRewards(user);\n if (pending > 0) {\n emit Claim(msg.sender, pending);\n int256 debtDelta = int256(pending);\n user.rewardDebt += debtDelta;\n totalRewardDebt += debtDelta;\n reward.safeTransfer(msg.sender, pending);\n }\n }\n\n function subDebt(uint256 amount, int256 debt)\n internal\n pure\n returns (uint256 result)\n {\n if (debt < 0) {\n result = amount.add(uint256(-debt));\n } else {\n result = amount.sub(uint256(debt));\n }\n }\n}\n" + }, + "contracts/governance/InitializableGovernable.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD InitializableGovernable Contract\n * @author Origin Protocol Inc\n */\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\n\nimport { Governable } from \"./Governable.sol\";\n\ncontract InitializableGovernable is Governable, Initializable {\n function _initialize(address _newGovernor) internal {\n _changeGovernor(_newGovernor);\n }\n}\n" + }, + "contracts/compensation/CompensationClaims.sol": { + "content": "pragma solidity 0.5.11;\n\nimport {\n Initializable\n} from \"@openzeppelin/upgrades/contracts/Initializable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\n\n/**\n * @title Compensation Claims\n * @author Origin Protocol Inc\n * @dev Airdrop for ERC20 tokens.\n *\n * Provides a coin airdrop with a verification period in which everyone\n * can check that all claims are correct before any actual funds are moved\n * to the contract.\n *\n * - Users can claim funds during the claim period.\n *\n * - The adjuster can set the amount of each user's claim,\n * but only when unlocked, and not during the claim period.\n *\n * - The governor can unlock and lock the adjuster, outside the claim period.\n * - The governor can start the claim period, if it's not started.\n * - The governor can collect any remaining funds after the claim period is over.\n *\n * Intended use sequence:\n *\n * 1. Governor unlocks the adjuster\n * 2. Adjuster uploads claims\n * 3. Governor locks the adjuster\n * 4. Everyone verifies that the claim amounts and totals are correct\n * 5. Payout funds are moved to the contract\n * 6. The claim period starts\n * 7. Users claim funds\n * 8. The claim period ends\n * 9. Governor can collect any remaing funds\n *\n */\ncontract CompensationClaims is Governable {\n address public adjuster;\n address public token;\n uint256 public end;\n uint256 public totalClaims;\n mapping(address => uint256) claims;\n bool public isAdjusterLocked;\n\n using SafeMath for uint256;\n\n event Claim(address indexed recipient, uint256 amount);\n event ClaimSet(address indexed recipient, uint256 amount);\n event Start(uint256 end);\n event Lock();\n event Unlock();\n event Collect(address indexed coin, uint256 amount);\n\n constructor(address _token, address _adjuster) public onlyGovernor {\n token = _token;\n adjuster = _adjuster;\n isAdjusterLocked = true;\n }\n\n function balanceOf(address _account) external view returns (uint256) {\n return claims[_account];\n }\n\n function decimals() external view returns (uint8) {\n return IERC20Decimals(token).decimals();\n }\n\n /* -- User -- */\n\n function claim(address _recipient) external onlyInClaimPeriod nonReentrant {\n uint256 amount = claims[_recipient];\n require(amount > 0, \"Amount must be greater than 0\");\n claims[_recipient] = 0;\n totalClaims = totalClaims.sub(amount);\n SafeERC20.safeTransfer(IERC20(token), _recipient, amount);\n emit Claim(_recipient, amount);\n }\n\n /* -- Adjustor -- */\n\n function setClaims(\n address[] calldata _addresses,\n uint256[] calldata _amounts\n ) external notInClaimPeriod onlyUnlockedAdjuster {\n require(\n _addresses.length == _amounts.length,\n \"Addresses and amounts must match\"\n );\n uint256 len = _addresses.length;\n for (uint256 i = 0; i < len; i++) {\n address recipient = _addresses[i];\n uint256 newAmount = _amounts[i];\n uint256 oldAmount = claims[recipient];\n claims[recipient] = newAmount;\n totalClaims = totalClaims.add(newAmount).sub(oldAmount);\n emit ClaimSet(recipient, newAmount);\n }\n }\n\n /* -- Governor -- */\n\n function lockAdjuster() external onlyGovernor notInClaimPeriod {\n _lockAdjuster();\n }\n\n function _lockAdjuster() internal {\n isAdjusterLocked = true;\n emit Lock();\n }\n\n function unlockAdjuster() external onlyGovernor notInClaimPeriod {\n isAdjusterLocked = false;\n emit Unlock();\n }\n\n function start(uint256 _seconds)\n external\n onlyGovernor\n notInClaimPeriod\n nonReentrant\n {\n require(totalClaims > 0, \"No claims\");\n uint256 funding = IERC20(token).balanceOf(address(this));\n require(funding >= totalClaims, \"Insufficient funds for all claims\");\n _lockAdjuster();\n end = block.timestamp.add(_seconds);\n require(end.sub(block.timestamp) < 31622400, \"Duration too long\"); // 31622400 = 366*24*60*60\n emit Start(end);\n }\n\n function collect(address _coin)\n external\n onlyGovernor\n notInClaimPeriod\n nonReentrant\n {\n uint256 amount = IERC20(_coin).balanceOf(address(this));\n SafeERC20.safeTransfer(IERC20(_coin), address(governor()), amount);\n emit Collect(_coin, amount);\n }\n\n /* -- modifiers -- */\n\n modifier onlyInClaimPeriod() {\n require(block.timestamp <= end, \"Should be in claim period\");\n _;\n }\n\n modifier notInClaimPeriod() {\n require(block.timestamp > end, \"Should not be in claim period\");\n _;\n }\n\n modifier onlyUnlockedAdjuster() {\n require(isAdjusterLocked == false, \"Adjuster must be unlocked\");\n require(msg.sender == adjuster, \"Must be adjuster\");\n _;\n }\n}\n\ninterface IERC20Decimals {\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/timelock/Timelock.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD Timelock Contract\n * @author Origin Protocol Inc\n */\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\ninterface CapitalPausable {\n function pauseCapital() external;\n\n function unpauseCapital() external;\n}\n\ncontract Timelock {\n using SafeMath for uint256;\n\n event NewAdmin(address indexed newAdmin);\n event NewPendingAdmin(address indexed newPendingAdmin);\n event NewDelay(uint256 indexed newDelay);\n event CancelTransaction(\n bytes32 indexed txHash,\n address indexed target,\n string signature,\n bytes data,\n uint256 eta\n );\n event ExecuteTransaction(\n bytes32 indexed txHash,\n address indexed target,\n string signature,\n bytes data,\n uint256 eta\n );\n event QueueTransaction(\n bytes32 indexed txHash,\n address indexed target,\n string signature,\n bytes data,\n uint256 eta\n );\n\n uint256 public constant GRACE_PERIOD = 3 days;\n uint256 public constant MINIMUM_DELAY = 1 minutes;\n uint256 public constant MAXIMUM_DELAY = 2 days;\n\n address public admin;\n address public pendingAdmin;\n uint256 public delay;\n\n mapping(bytes32 => bool) public queuedTransactions;\n\n /**\n * @dev Throws if called by any account other than the Admin.\n */\n modifier onlyAdmin() {\n require(msg.sender == admin, \"Caller is not the admin\");\n _;\n }\n\n constructor(address admin_, uint256 delay_) public {\n require(\n delay_ >= MINIMUM_DELAY,\n \"Timelock::constructor: Delay must exceed minimum delay.\"\n );\n require(\n delay_ <= MAXIMUM_DELAY,\n \"Timelock::setDelay: Delay must not exceed maximum delay.\"\n );\n\n admin = admin_;\n delay = delay_;\n }\n\n function setDelay(uint256 delay_) public {\n require(\n msg.sender == address(this),\n \"Timelock::setDelay: Call must come from Timelock.\"\n );\n require(\n delay_ >= MINIMUM_DELAY,\n \"Timelock::setDelay: Delay must exceed minimum delay.\"\n );\n require(\n delay_ <= MAXIMUM_DELAY,\n \"Timelock::setDelay: Delay must not exceed maximum delay.\"\n );\n delay = delay_;\n\n emit NewDelay(delay);\n }\n\n function acceptAdmin() public {\n require(\n msg.sender == pendingAdmin,\n \"Timelock::acceptAdmin: Call must come from pendingAdmin.\"\n );\n admin = msg.sender;\n pendingAdmin = address(0);\n\n emit NewAdmin(admin);\n }\n\n function setPendingAdmin(address pendingAdmin_) public onlyAdmin {\n pendingAdmin = pendingAdmin_;\n\n emit NewPendingAdmin(pendingAdmin);\n }\n\n function queueTransaction(\n address target,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) internal returns (bytes32) {\n require(\n msg.sender == admin,\n \"Timelock::queueTransaction: Call must come from admin.\"\n );\n require(\n eta >= getBlockTimestamp().add(delay),\n \"Timelock::queueTransaction: Estimated execution block must satisfy delay.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, signature, keccak256(data), eta)\n );\n queuedTransactions[txHash] = true;\n\n emit QueueTransaction(txHash, target, signature, data, eta);\n return txHash;\n }\n\n function cancelTransaction(\n address target,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) internal {\n require(\n msg.sender == admin,\n \"Timelock::cancelTransaction: Call must come from admin.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, signature, keccak256(data), eta)\n );\n queuedTransactions[txHash] = false;\n\n emit CancelTransaction(txHash, target, signature, data, eta);\n }\n\n function executeTransaction(\n address target,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) internal returns (bytes memory) {\n require(\n msg.sender == admin,\n \"Timelock::executeTransaction: Call must come from admin.\"\n );\n\n bytes32 txHash = keccak256(\n abi.encode(target, signature, keccak256(data), eta)\n );\n require(\n queuedTransactions[txHash],\n \"Timelock::executeTransaction: Transaction hasn't been queued.\"\n );\n require(\n getBlockTimestamp() >= eta,\n \"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\"\n );\n require(\n getBlockTimestamp() <= eta.add(GRACE_PERIOD),\n \"Timelock::executeTransaction: Transaction is stale.\"\n );\n\n queuedTransactions[txHash] = false;\n\n bytes memory callData;\n\n if (bytes(signature).length == 0) {\n callData = data;\n } else {\n callData = abi.encodePacked(\n bytes4(keccak256(bytes(signature))),\n data\n );\n }\n\n (bool success, bytes memory returnData) = target.call(callData);\n require(\n success,\n \"Timelock::executeTransaction: Transaction execution reverted.\"\n );\n\n emit ExecuteTransaction(txHash, target, signature, data, eta);\n\n return returnData;\n }\n\n function getBlockTimestamp() internal view returns (uint256) {\n // solium-disable-next-line security/no-block-members\n return block.timestamp;\n }\n\n function pauseCapital(address target) external {\n require(\n msg.sender == admin,\n \"Timelock::pauseCapital: Call must come from admin.\"\n );\n CapitalPausable(target).pauseCapital();\n }\n\n function unpauseCapital(address target) external {\n require(\n msg.sender == admin,\n \"Timelock::unpauseCapital: Call must come from admin.\"\n );\n CapitalPausable(target).unpauseCapital();\n }\n}\n" + }, + "contracts/governance/Governor.sol": { + "content": "pragma solidity 0.5.11;\npragma experimental ABIEncoderV2;\n\nimport \"./../timelock/Timelock.sol\";\n\n// Modeled off of Compound's Governor Alpha\n// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol\ncontract Governor is Timelock {\n // @notice The total number of proposals\n uint256 public proposalCount;\n\n struct Proposal {\n // @notice Unique id for looking up a proposal\n uint256 id;\n // @notice Creator of the proposal\n address proposer;\n // @notice The timestamp that the proposal will be available for\n // execution, set once the vote succeeds\n uint256 eta;\n // @notice the ordered list of target addresses for calls to be made\n address[] targets;\n // @notice The ordered list of function signatures to be called\n string[] signatures;\n // @notice The ordered list of calldata to be passed to each call\n bytes[] calldatas;\n // @notice Flag marking whether the proposal has been executed\n bool executed;\n }\n\n // @notice The official record of all proposals ever proposed\n mapping(uint256 => Proposal) public proposals;\n\n // @notice An event emitted when a new proposal is created\n event ProposalCreated(\n uint256 id,\n address proposer,\n address[] targets,\n string[] signatures,\n bytes[] calldatas,\n string description\n );\n\n // @notice An event emitted when a proposal has been queued in the Timelock\n event ProposalQueued(uint256 id, uint256 eta);\n\n // @notice An event emitted when a proposal has been executed in the Timelock\n event ProposalExecuted(uint256 id);\n\n // @notice An event emitted when a proposal has been cancelled\n event ProposalCancelled(uint256 id);\n\n uint256 public constant MAX_OPERATIONS = 16;\n\n // @notice Possible states that a proposal may be in\n enum ProposalState { Pending, Queued, Expired, Executed }\n\n constructor(address admin_, uint256 delay_)\n public\n Timelock(admin_, delay_)\n {}\n\n /**\n * @notice Propose Governance call(s)\n * @param targets Ordered list of targeted addresses\n * @param signatures Orderd list of function signatures to be called\n * @param calldatas Orderded list of calldata to be passed with each call\n * @param description Description of the governance\n * @return uint256 id of the proposal\n */\n function propose(\n address[] memory targets,\n string[] memory signatures,\n bytes[] memory calldatas,\n string memory description\n ) public returns (uint256) {\n // Allow anyone to propose for now, since only admin can queue the\n // transaction it should be harmless, you just need to pay the gas\n require(\n targets.length == signatures.length &&\n targets.length == calldatas.length,\n \"Governor::propose: proposal function information arity mismatch\"\n );\n require(targets.length != 0, \"Governor::propose: must provide actions\");\n require(\n targets.length <= MAX_OPERATIONS,\n \"Governor::propose: too many actions\"\n );\n\n proposalCount++;\n Proposal memory newProposal = Proposal({\n id: proposalCount,\n proposer: msg.sender,\n eta: 0,\n targets: targets,\n signatures: signatures,\n calldatas: calldatas,\n executed: false\n });\n\n proposals[newProposal.id] = newProposal;\n\n emit ProposalCreated(\n newProposal.id,\n msg.sender,\n targets,\n signatures,\n calldatas,\n description\n );\n return newProposal.id;\n }\n\n /**\n * @notice Queue a proposal for execution\n * @param proposalId id of the proposal to queue\n */\n function queue(uint256 proposalId) public onlyAdmin {\n require(\n state(proposalId) == ProposalState.Pending,\n \"Governor::queue: proposal can only be queued if it is pending\"\n );\n Proposal storage proposal = proposals[proposalId];\n proposal.eta = block.timestamp.add(delay);\n\n for (uint256 i = 0; i < proposal.targets.length; i++) {\n _queueOrRevert(\n proposal.targets[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n proposal.eta\n );\n }\n\n emit ProposalQueued(proposal.id, proposal.eta);\n }\n\n /**\n * @notice Get the state of a proposal\n * @param proposalId id of the proposal\n * @return ProposalState\n */\n function state(uint256 proposalId) public view returns (ProposalState) {\n require(\n proposalCount >= proposalId && proposalId > 0,\n \"Governor::state: invalid proposal id\"\n );\n Proposal storage proposal = proposals[proposalId];\n if (proposal.executed) {\n return ProposalState.Executed;\n } else if (proposal.eta == 0) {\n return ProposalState.Pending;\n } else if (block.timestamp >= proposal.eta.add(GRACE_PERIOD)) {\n return ProposalState.Expired;\n } else {\n return ProposalState.Queued;\n }\n }\n\n function _queueOrRevert(\n address target,\n string memory signature,\n bytes memory data,\n uint256 eta\n ) internal {\n require(\n !queuedTransactions[keccak256(\n abi.encode(target, signature, keccak256(data), eta)\n )],\n \"Governor::_queueOrRevert: proposal action already queued at eta\"\n );\n require(\n queuedTransactions[queueTransaction(target, signature, data, eta)],\n \"Governor::_queueOrRevert: failed to queue transaction\"\n );\n }\n\n /**\n * @notice Execute a proposal.\n * @param proposalId id of the proposal\n */\n function execute(uint256 proposalId) public {\n require(\n state(proposalId) == ProposalState.Queued,\n \"Governor::execute: proposal can only be executed if it is queued\"\n );\n Proposal storage proposal = proposals[proposalId];\n proposal.executed = true;\n for (uint256 i = 0; i < proposal.targets.length; i++) {\n executeTransaction(\n proposal.targets[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n proposal.eta\n );\n }\n emit ProposalExecuted(proposalId);\n }\n\n /**\n * @notice Cancel a proposal.\n * @param proposalId id of the proposal\n */\n function cancel(uint256 proposalId) public onlyAdmin {\n ProposalState proposalState = state(proposalId);\n\n require(\n proposalState == ProposalState.Queued ||\n proposalState == ProposalState.Pending,\n \"Governor::execute: proposal can only be cancelled if it is queued or pending\"\n );\n Proposal storage proposal = proposals[proposalId];\n proposal.eta = 1; // To mark the proposal as `Expired`\n for (uint256 i = 0; i < proposal.targets.length; i++) {\n cancelTransaction(\n proposal.targets[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n proposal.eta\n );\n }\n emit ProposalCancelled(proposalId);\n }\n\n /**\n * @notice Get the actions that a proposal will take.\n * @param proposalId id of the proposal\n */\n function getActions(uint256 proposalId)\n public\n view\n returns (\n address[] memory targets,\n string[] memory signatures,\n bytes[] memory calldatas\n )\n {\n Proposal storage p = proposals[proposalId];\n return (p.targets, p.signatures, p.calldatas);\n }\n}\n" + }, + "contracts/flipper/Flipper.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../governance/Governable.sol\";\nimport \"../token/OUSD.sol\";\nimport \"../interfaces/Tether.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n// Contract to exchange usdt, usdc, dai from and to ousd.\n// - 1 to 1. No slippage\n// - Optimized for low gas usage\n// - No guarantee of availability\n\ncontract Flipper is Governable {\n using SafeERC20 for IERC20;\n\n uint256 constant MAXIMUM_PER_TRADE = (25000 * 1e18);\n\n // Saves approx 4K gas per swap by using hardcoded addresses.\n IERC20 dai = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F);\n OUSD constant ousd = OUSD(0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86);\n IERC20 usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n Tether constant usdt = Tether(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n // -----------\n // Constructor\n // -----------\n constructor() public {}\n\n // -----------------\n // Trading functions\n // -----------------\n\n /// @notice Purchase OUSD with Dai\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithDai(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(dai.transferFrom(msg.sender, address(this), amount));\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for Dai\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForDai(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(dai.transfer(msg.sender, amount));\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n /// @notice Purchase OUSD with USDC\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithUsdc(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // Potential rounding error is an intentional tradeoff\n require(usdc.transferFrom(msg.sender, address(this), amount / 1e12));\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for USDC\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForUsdc(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n require(usdc.transfer(msg.sender, amount / 1e12));\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n /// @notice Purchase OUSD with USDT\n /// @param amount Amount of OUSD to purchase, in 18 fixed decimals.\n function buyOusdWithUsdt(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // Potential rounding error is an intentional tradeoff\n // USDT does not return a boolean and reverts,\n // so no need for a require.\n usdt.transferFrom(msg.sender, address(this), amount / 1e12);\n require(ousd.transfer(msg.sender, amount));\n }\n\n /// @notice Sell OUSD for USDT\n /// @param amount Amount of OUSD to sell, in 18 fixed decimals.\n function sellOusdForUsdt(uint256 amount) external {\n require(amount <= MAXIMUM_PER_TRADE, \"Amount too large\");\n // USDT does not return a boolean and reverts,\n // so no need for a require.\n usdt.transfer(msg.sender, amount / 1e12);\n require(ousd.transferFrom(msg.sender, address(this), amount));\n }\n\n // --------------------\n // Governance functions\n // --------------------\n\n /// @dev Opting into yield reduces the gas cost per transfer by about 4K, since\n /// ousd needs to do less accounting and one less storage write.\n function rebaseOptIn() external onlyGovernor nonReentrant {\n ousd.rebaseOptIn();\n }\n\n /// @notice Owner function to withdraw a specific amount of a token\n function withdraw(address token, uint256 amount)\n external\n onlyGovernor\n nonReentrant\n {\n IERC20(token).safeTransfer(_governor(), amount);\n }\n\n /// @notice Owner function to withdraw all tradable tokens\n /// @dev Equivalent to \"pausing\" the contract.\n function withdrawAll() external onlyGovernor nonReentrant {\n IERC20(dai).safeTransfer(_governor(), dai.balanceOf(address(this)));\n IERC20(ousd).safeTransfer(_governor(), ousd.balanceOf(address(this)));\n IERC20(address(usdt)).safeTransfer(\n _governor(),\n usdt.balanceOf(address(this))\n );\n IERC20(usdc).safeTransfer(_governor(), usdc.balanceOf(address(this)));\n }\n}\n" + }, + "contracts/buyback/BuybackConstructor.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { Governable } from \"../governance/Governable.sol\";\n\nimport { IUniswapV2Router } from \"../interfaces/uniswap/IUniswapV2Router02.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\ncontract BuybackConstructor is Governable {\n using SafeERC20 for IERC20;\n\n event UniswapUpdated(address _address);\n\n // Address of Uniswap\n address public uniswapAddr = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;\n\n // Address of OUSD Vault\n address public vaultAddr = 0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70;\n\n // Swap from OUSD\n IERC20 ousd = IERC20(0x2A8e1E676Ec238d8A992307B495b45B3fEAa5e86);\n\n // Swap to OGN\n IERC20 ogn = IERC20(0x8207c1FfC5B6804F6024322CcF34F29c3541Ae26);\n\n // USDT for Uniswap path\n IERC20 usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n\n\n constructor(\n address _uniswapAddr,\n address _vaultAddr,\n address _ousd,\n address _ogn,\n address _usdt\n ) public {\n uniswapAddr = _uniswapAddr;\n vaultAddr = _vaultAddr;\n ousd = IERC20(_ousd);\n ogn = IERC20(_ogn);\n usdt = IERC20(_usdt);\n // Give approval to Uniswap router for OUSD, this is handled\n // by setUniswapAddr in the production contract\n ousd.safeApprove(uniswapAddr, 0);\n ousd.safeApprove(uniswapAddr, uint256(-1));\n }\n\n /**\n * @dev Verifies that the caller is the OUSD Vault.\n */\n modifier onlyVault() {\n require(vaultAddr == msg.sender, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @dev Set address of Uniswap for performing liquidation of strategy reward\n * tokens. Setting to 0x0 will pause swaps.\n * @param _address Address of Uniswap\n */\n function setUniswapAddr(address _address) external onlyGovernor {\n uniswapAddr = _address;\n // Give Uniswap unlimited OUSD allowance\n ousd.safeApprove(uniswapAddr, 0);\n ousd.safeApprove(uniswapAddr, uint256(-1));\n emit UniswapUpdated(_address);\n }\n\n /**\n * @dev Execute a swap of OGN for OUSD via Uniswap or Uniswap compatible\n * protocol (e.g. Sushiswap)\n **/\n function swap() external onlyVault {\n if (uniswapAddr == address(0)) return;\n\n uint256 sourceAmount = ousd.balanceOf(address(this));\n if (sourceAmount < 1000 * 1e18) return;\n\n // Uniswap redemption path\n address[] memory path = new address[](4);\n path[0] = address(ousd);\n path[1] = address(usdt);\n path[2] = IUniswapV2Router(uniswapAddr).WETH();\n path[3] = address(ogn);\n IUniswapV2Router(uniswapAddr).swapExactTokensForTokens(\n sourceAmount,\n uint256(0),\n path,\n address(this),\n now\n );\n }\n\n /**\n * @notice Owner function to withdraw a specific amount of a token\n */\n function transferToken(address token, uint256 amount)\n external\n onlyGovernor\n nonReentrant\n {\n IERC20(token).safeTransfer(_governor(), amount);\n }\n}\n" + }, + "contracts/crytic/PropertiesOUSDTransferable.sol": { + "content": "import \"./interfaces.sol\";\nimport \"../token/OUSD.sol\";\n\ncontract PropertiesOUSDTransferable is CryticInterface, OUSD {\n function init_total_supply() public returns (bool) {\n return\n this.totalSupply() >= 0 && this.totalSupply() == initialTotalSupply;\n }\n\n function init_owner_balance() public returns (bool) {\n return initialBalance_owner == this.balanceOf(crytic_owner);\n }\n\n function init_user_balance() public returns (bool) {\n return initialBalance_user == this.balanceOf(crytic_user);\n }\n\n function init_attacker_balance() public returns (bool) {\n return initialBalance_attacker == this.balanceOf(crytic_attacker);\n }\n\n function init_caller_balance() public returns (bool) {\n return this.balanceOf(msg.sender) > 0;\n }\n\n function init_total_supply_is_balances() public returns (bool) {\n return\n this.balanceOf(crytic_owner) +\n this.balanceOf(crytic_user) +\n this.balanceOf(crytic_attacker) ==\n this.totalSupply();\n }\n\n function crytic_zero_always_empty_ERC20Properties() public returns (bool) {\n return this.balanceOf(address(0x0)) == 0;\n }\n\n function crytic_approve_overwrites() public returns (bool) {\n bool approve_return;\n approve_return = approve(crytic_user, 10);\n require(approve_return);\n approve_return = approve(crytic_user, 20);\n require(approve_return);\n return this.allowance(msg.sender, crytic_user) == 20;\n }\n\n function crytic_less_than_total_ERC20Properties() public returns (bool) {\n return this.balanceOf(msg.sender) <= totalSupply();\n }\n\n function crytic_revert_transfer_to_zero_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n if (this.balanceOf(msg.sender) == 0) {\n revert();\n }\n return transfer(address(0x0), this.balanceOf(msg.sender));\n }\n\n function crytic_revert_transferFrom_to_zero_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n if (balance == 0) {\n revert();\n }\n approve(msg.sender, balance);\n return\n transferFrom(msg.sender, address(0x0), this.balanceOf(msg.sender));\n }\n\n function crytic_self_transferFrom_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n bool approve_return = approve(msg.sender, balance);\n bool transfer_return = transferFrom(msg.sender, msg.sender, balance);\n return\n (this.balanceOf(msg.sender) == balance) &&\n approve_return &&\n transfer_return;\n }\n\n function crytic_self_transferFrom_to_other_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n bool approve_return = approve(msg.sender, balance);\n address other = crytic_user;\n if (other == msg.sender) {\n other = crytic_owner;\n }\n bool transfer_return = transferFrom(msg.sender, other, balance);\n return\n (this.balanceOf(msg.sender) == 0) &&\n approve_return &&\n transfer_return;\n }\n\n function crytic_self_transfer_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n bool transfer_return = transfer(msg.sender, balance);\n return (this.balanceOf(msg.sender) == balance) && transfer_return;\n }\n\n function crytic_transfer_to_other_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n address other = crytic_user;\n if (other == msg.sender) {\n other = crytic_owner;\n }\n if (balance >= 1) {\n bool transfer_other = transfer(other, 1);\n return\n (this.balanceOf(msg.sender) == balance - 1) &&\n (this.balanceOf(other) >= 1) &&\n transfer_other;\n }\n return true;\n }\n\n function crytic_revert_transfer_to_user_ERC20PropertiesTransferable()\n public\n returns (bool)\n {\n uint256 balance = this.balanceOf(msg.sender);\n if (balance == (2**128 - 1)) return true;\n bool transfer_other = transfer(crytic_user, balance + 1);\n return transfer_other;\n }\n}\n" + }, + "contracts/crytic/interfaces.sol": { + "content": "contract CryticInterface {\n address internal crytic_owner = address(\n 0x627306090abaB3A6e1400e9345bC60c78a8BEf57\n );\n address internal crytic_user = address(\n 0xf17f52151EbEF6C7334FAD080c5704D77216b732\n );\n address internal crytic_attacker = address(\n 0xC5fdf4076b8F3A5357c5E395ab970B5B54098Fef\n );\n uint256 internal initialTotalSupply;\n uint256 internal initialBalance_owner;\n uint256 internal initialBalance_user;\n uint256 internal initialBalance_attacker;\n}\n" + }, + "contracts/crytic/TestOUSDTransferable.sol": { + "content": "import \"./PropertiesOUSDTransferable.sol\";\n\ncontract TestOUSDTransferable is PropertiesOUSDTransferable {\n constructor() public {\n // Existing addresses:\n // - crytic_owner: If the contract has an owner, it must be crytic_owner\n // - crytic_user: Legitimate user\n // - crytic_attacker: Attacker\n //\n // Add below a minimal configuration:\n // - crytic_owner must have some tokens\n // - crytic_user must have some tokens\n // - crytic_attacker must have some tokens\n\n rebasingCredits = 0;\n rebasingCreditsPerToken = 1e18;\n vaultAddress = crytic_owner;\n nonRebasingSupply = 0;\n\n initialTotalSupply = ~uint128(0);\n initialBalance_owner = initialTotalSupply / 3;\n _mint(crytic_owner, initialBalance_owner);\n initialBalance_user = initialTotalSupply / 3;\n _mint(crytic_user, initialBalance_user);\n initialBalance_attacker = initialTotalSupply / 3;\n _mint(crytic_attacker, initialBalance_attacker);\n }\n\n function initialize(\n string calldata _nameArg,\n string calldata _symbolArg,\n address _vaultAddress\n ) external {\n revert();\n } // We don't need to call initialize\n}\n" + }, + "contracts/mocks/MockVault.sol": { + "content": "pragma solidity 0.5.11;\n\nimport { VaultCore } from \"../vault/VaultCore.sol\";\nimport { VaultInitializer } from \"../vault/VaultInitializer.sol\";\n\ncontract MockVault is VaultCore, VaultInitializer {\n uint256 storedTotalValue;\n\n function setTotalValue(uint256 _totalValue) public {\n storedTotalValue = _totalValue;\n }\n\n function totalValue() external view returns (uint256) {\n return storedTotalValue;\n }\n\n function _totalValue() internal view returns (uint256) {\n return storedTotalValue;\n }\n\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external onlyGovernor {\n maxSupplyDiff = _maxSupplyDiff;\n }\n}\n" + }, + "contracts/vault/VaultInitializer.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD VaultInitializer Contract\n * @notice The Vault contract initializes the vault.\n * @author Origin Protocol Inc\n */\n\nimport \"./VaultStorage.sol\";\n\ncontract VaultInitializer is VaultStorage {\n function initialize(address _priceProvider, address _ousd)\n external\n onlyGovernor\n initializer\n {\n require(_priceProvider != address(0), \"PriceProvider address is zero\");\n require(_ousd != address(0), \"oUSD address is zero\");\n\n oUSD = OUSD(_ousd);\n\n priceProvider = _priceProvider;\n\n rebasePaused = false;\n capitalPaused = true;\n\n // Initial redeem fee of 0 basis points\n redeemFeeBps = 0;\n // Initial Vault buffer of 0%\n vaultBuffer = 0;\n // Initial allocate threshold of 25,000 OUSD\n autoAllocateThreshold = 25000e18;\n // Threshold for rebasing\n rebaseThreshold = 1000e18;\n }\n}\n" + }, + "contracts/vault/Vault.sol": { + "content": "pragma solidity 0.5.11;\n\n/**\n * @title OUSD VaultInitializer Contract\n * @notice The VaultInitializer sets up the initial contract.\n * @author Origin Protocol Inc\n */\nimport { VaultInitializer } from \"./VaultInitializer.sol\";\nimport { VaultAdmin } from \"./VaultAdmin.sol\";\n\ncontract Vault is VaultInitializer, VaultAdmin {}\n" + }, + "contracts/mocks/MockChainlinkOracleFeed.sol": { + "content": "pragma solidity 0.5.11;\n\nimport \"../interfaces/chainlink/AggregatorV3Interface.sol\";\n\ncontract MockChainlinkOracleFeed is AggregatorV3Interface {\n int256 price;\n uint8 numDecimals;\n\n constructor(int256 _price, uint8 _decimals) public {\n price = _price;\n numDecimals = _decimals;\n }\n\n function decimals() external view returns (uint8) {\n return numDecimals;\n }\n\n function description() external view returns (string memory) {\n return \"MockOracleEthFeed\";\n }\n\n function version() external view returns (uint256) {\n return 1;\n }\n\n function setPrice(int256 _price) public {\n price = _price;\n }\n\n function setDecimals(uint8 _decimals) public {\n numDecimals = _decimals;\n }\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(uint80 _roundId)\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n )\n {\n roundId = _roundId;\n answer = price;\n startedAt = 0;\n updatedAt = 0;\n answeredInRound = 0;\n }\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n )\n {\n roundId = 0;\n answer = price;\n startedAt = 0;\n updatedAt = 0;\n answeredInRound = 0;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "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/contracts/hardhat.config.js b/contracts/hardhat.config.js index dd958f4375..014a5570c8 100644 --- a/contracts/hardhat.config.js +++ b/contracts/hardhat.config.js @@ -7,7 +7,7 @@ require("hardhat-contract-sizer"); require("hardhat-deploy-ethers"); require("@openzeppelin/hardhat-upgrades"); -const { accounts, fund, mint, redeem } = require("./tasks/account"); +const { accounts, fund, mint, redeem, transfer } = require("./tasks/account"); const { debug } = require("./tasks/debug"); const { env } = require("./tasks/env"); const { execute, executeOnFork, proposal } = require("./tasks/governance"); @@ -75,6 +75,11 @@ task("redeem", "Redeem OUSD on local or fork") .addOptionalParam("index", "Account start index") .addOptionalParam("amount", "Amount of OUSD to mint") .setAction(redeem); +task("transfer", "Transfer OUSD") + .addParam("index", "Account index") + .addParam("amount", "Amount of OUSD to transfer") + .addParam("to", "Destination address") + .setAction(transfer); // Debug tasks. task("debug", "Print info about contracts and their configs", debug); diff --git a/contracts/storageLayout/mainnet/Buyback.json b/contracts/storageLayout/mainnet/Buyback.json new file mode 100644 index 0000000000..e2deeac812 --- /dev/null +++ b/contracts/storageLayout/mainnet/Buyback.json @@ -0,0 +1,15 @@ +{ + "storage": [ + { + "contract": "Buyback", + "label": "uniswapAddr", + "type": "t_address", + "src": "contracts/buyback/Buyback.sol:15" + } + ], + "types": { + "t_address": { + "label": "address" + } + } +} \ No newline at end of file diff --git a/contracts/storageLayout/mainnet/OracleRouter.json b/contracts/storageLayout/mainnet/OracleRouter.json new file mode 100644 index 0000000000..2af34daf38 --- /dev/null +++ b/contracts/storageLayout/mainnet/OracleRouter.json @@ -0,0 +1,4 @@ +{ + "storage": [], + "types": {} +} \ No newline at end of file diff --git a/contracts/storageLayout/mainnet/VaultAdmin.json b/contracts/storageLayout/mainnet/VaultAdmin.json index 6f90384da8..c77e5c5b90 100644 --- a/contracts/storageLayout/mainnet/VaultAdmin.json +++ b/contracts/storageLayout/mainnet/VaultAdmin.json @@ -21,7 +21,7 @@ { "contract": "VaultStorage", "label": "assets", - "type": "t_mapping(t_address,t_struct(Asset)17088_storage)", + "type": "t_mapping(t_address,t_struct(Asset)18894_storage)", "src": "contracts/vault/VaultStorage.sol:55" }, { @@ -33,7 +33,7 @@ { "contract": "VaultStorage", "label": "strategies", - "type": "t_mapping(t_address,t_struct(Strategy)17100_storage)", + "type": "t_mapping(t_address,t_struct(Strategy)18906_storage)", "src": "contracts/vault/VaultStorage.sol:63" }, { @@ -87,7 +87,7 @@ { "contract": "VaultStorage", "label": "oUSD", - "type": "t_contract(OUSD)13567", + "type": "t_contract(OUSD)15327", "src": "contracts/vault/VaultStorage.sol:80" }, { @@ -134,13 +134,13 @@ } ], "types": { - "t_mapping(t_address,t_struct(Asset)17088_storage)": { + "t_mapping(t_address,t_struct(Asset)18894_storage)": { "label": "mapping(address => struct VaultStorage.Asset)" }, "t_address": { "label": "address" }, - "t_struct(Asset)17088_storage": { + "t_struct(Asset)18894_storage": { "label": "struct VaultStorage.Asset", "members": [ { @@ -155,10 +155,10 @@ "t_array(t_address)dyn_storage": { "label": "address[]" }, - "t_mapping(t_address,t_struct(Strategy)17100_storage)": { + "t_mapping(t_address,t_struct(Strategy)18906_storage)": { "label": "mapping(address => struct VaultStorage.Strategy)" }, - "t_struct(Strategy)17100_storage": { + "t_struct(Strategy)18906_storage": { "label": "struct VaultStorage.Strategy", "members": [ { @@ -174,7 +174,7 @@ "t_uint256": { "label": "uint256" }, - "t_contract(OUSD)13567": { + "t_contract(OUSD)15327": { "label": "contract OUSD" }, "t_mapping(t_address,t_address)": { diff --git a/contracts/storageLayout/mainnet/VaultCore.json b/contracts/storageLayout/mainnet/VaultCore.json index 630024aacb..c77e5c5b90 100644 --- a/contracts/storageLayout/mainnet/VaultCore.json +++ b/contracts/storageLayout/mainnet/VaultCore.json @@ -21,7 +21,7 @@ { "contract": "VaultStorage", "label": "assets", - "type": "t_mapping(t_address,t_struct(Asset)16977_storage)", + "type": "t_mapping(t_address,t_struct(Asset)18894_storage)", "src": "contracts/vault/VaultStorage.sol:55" }, { @@ -33,7 +33,7 @@ { "contract": "VaultStorage", "label": "strategies", - "type": "t_mapping(t_address,t_struct(Strategy)16989_storage)", + "type": "t_mapping(t_address,t_struct(Strategy)18906_storage)", "src": "contracts/vault/VaultStorage.sol:63" }, { @@ -87,7 +87,7 @@ { "contract": "VaultStorage", "label": "oUSD", - "type": "t_contract(OUSD)13422", + "type": "t_contract(OUSD)15327", "src": "contracts/vault/VaultStorage.sol:80" }, { @@ -134,13 +134,13 @@ } ], "types": { - "t_mapping(t_address,t_struct(Asset)16977_storage)": { + "t_mapping(t_address,t_struct(Asset)18894_storage)": { "label": "mapping(address => struct VaultStorage.Asset)" }, "t_address": { "label": "address" }, - "t_struct(Asset)16977_storage": { + "t_struct(Asset)18894_storage": { "label": "struct VaultStorage.Asset", "members": [ { @@ -155,10 +155,10 @@ "t_array(t_address)dyn_storage": { "label": "address[]" }, - "t_mapping(t_address,t_struct(Strategy)16989_storage)": { + "t_mapping(t_address,t_struct(Strategy)18906_storage)": { "label": "mapping(address => struct VaultStorage.Strategy)" }, - "t_struct(Strategy)16989_storage": { + "t_struct(Strategy)18906_storage": { "label": "struct VaultStorage.Strategy", "members": [ { @@ -174,7 +174,7 @@ "t_uint256": { "label": "uint256" }, - "t_contract(OUSD)13422": { + "t_contract(OUSD)15327": { "label": "contract OUSD" }, "t_mapping(t_address,t_address)": { diff --git a/contracts/tasks/account.js b/contracts/tasks/account.js index fac575f5e1..67da3e571e 100644 --- a/contracts/tasks/account.js +++ b/contracts/tasks/account.js @@ -269,9 +269,58 @@ async function redeem(taskArguments, hre) { } } +// Sends OUSD to a destination address. +async function transfer(taskArguments) { + const { + ousdUnits, + ousdUnitsFormat, + isFork, + isLocalHost, + } = require("../test/helpers"); + + if (!isFork && !isLocalHost) { + throw new Error("Task can only be used on local or fork"); + } + + const ousdProxy = await ethers.getContract("OUSDProxy"); + const ousd = await ethers.getContractAt("OUSD", ousdProxy.address); + + const index = Number(taskArguments.index); + const amount = taskArguments.amount; + const to = taskArguments.to; + + const signers = await hre.ethers.getSigners(); + const signer = signers[index]; + + // Print balances prior to the transfer + console.log("\nOUSD balances prior transfer"); + console.log( + `${signer.address}: ${ousdUnitsFormat( + await ousd.balanceOf(signer.address) + )} OUSD` + ); + console.log(`${to}: ${ousdUnitsFormat(await ousd.balanceOf(to))} OUSD`); + + // Send OUSD. + console.log( + `\nTransferring ${amount} OUSD from ${signer.address} to ${to}...` + ); + await ousd.connect(signer).transfer(to, ousdUnits(amount)); + + // Print balances after to the transfer + console.log("\nOUSD balances after transfer"); + console.log( + `${signer.address}: ${ousdUnitsFormat( + await ousd.balanceOf(signer.address) + )} OUSD` + ); + console.log(`${to}: ${ousdUnitsFormat(await ousd.balanceOf(to))} OUSD`); +} + module.exports = { accounts, fund, mint, redeem, + transfer, }; diff --git a/contracts/tasks/debug.js b/contracts/tasks/debug.js index 1a1c760403..f3b3f9476e 100644 --- a/contracts/tasks/debug.js +++ b/contracts/tasks/debug.js @@ -147,8 +147,8 @@ async function debug(taskArguments, hre) { const priceUSDC = await oracleRouter.price(addresses.mainnet.USDC); const priceUSDT = await oracleRouter.price(addresses.mainnet.USDT); console.log(`DAI price : ${formatUnits(priceDAI, 8)} USD`); - console.log(`USDT price: ${formatUnits(priceUSDC, 8)} USD`); - console.log(`USDC price: ${formatUnits(priceUSDT, 8)} USD`); + console.log(`USDC price: ${formatUnits(priceUSDC, 8)} USD`); + console.log(`USDT price: ${formatUnits(priceUSDT, 8)} USD`); // // Vault diff --git a/dapp/network.mainnet.json b/dapp/network.mainnet.json index d88d3b1ee8..c7acb9a17e 100644 --- a/dapp/network.mainnet.json +++ b/dapp/network.mainnet.json @@ -3608,6 +3608,237 @@ } ] }, + "Flipper": { + "address": "0xcecaD69d7D4Ed6D52eFcFA028aF8732F27e08F70", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithUsdt", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithDai", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claimGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdrawAll", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForDai", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithUsdc", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForUsdc", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isGovernor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForUsdt", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "rebaseOptIn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "PendingGovernorshipTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "GovernorshipTransferred", + "type": "event" + } + ] + }, "Governor": { "address": "0x8e7bDFeCd1164C46ad51b58e49A611F954D23377", "abi": [ @@ -10417,7 +10648,7 @@ ] }, "VaultAdmin": { - "address": "0xb5f7E47Bc7D271b3df4824BDcFBB279a719F8Ae6", + "address": "0x8E55b527901BC88206a1cE5C292B2404bcb8F76D", "abi": [ { "constant": false, @@ -10514,6 +10745,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDMint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -10574,27 +10826,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDRedeem", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": false, "inputs": [ @@ -10735,8 +10966,14 @@ }, { "constant": false, - "inputs": [], - "name": "claimGovernance", + "inputs": [ + { + "internalType": "address", + "name": "_strategyAddr", + "type": "address" + } + ], + "name": "withdrawAllFromStrategy", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -10744,38 +10981,26 @@ }, { "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_maxSupplyDiff", - "type": "uint256" - } - ], - "name": "setMaxSupplyDiff", + "inputs": [], + "name": "claimGovernance", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDMint", - "outputs": [ { "internalType": "uint256", - "name": "", + "name": "_maxSupplyDiff", "type": "uint256" } ], + "name": "setMaxSupplyDiff", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -10823,6 +11048,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -11002,6 +11248,15 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [], + "name": "withdrawAllFromStrategies", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -11378,7 +11633,7 @@ ] }, "VaultCore": { - "address": "0x3e803eEA623eE4793f0f49790A813811da5249f4", + "address": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", "abi": [ { "constant": true, @@ -12401,8 +12656,8 @@ } ] }, - "Flipper": { - "address": "0xcecaD69d7D4Ed6D52eFcFA028aF8732F27e08F70", + "Buyback": { + "address": "0x7294CD3C3eb4097b03E1A61EB2AD280D3dD265e6", "abi": [ { "constant": true, @@ -12422,31 +12677,36 @@ { "constant": false, "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], - "name": "buyOusdWithUsdt", + "name": "transferToken", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "uniswapAddr", + "outputs": [ { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "buyOusdWithDai", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -12461,22 +12721,7 @@ { "constant": false, "inputs": [], - "name": "withdrawAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "sellOusdForDai", + "name": "swap", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -12486,27 +12731,12 @@ "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "buyOusdWithUsdc", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "address", + "name": "_address", + "type": "address" } ], - "name": "sellOusdForUsdc", + "name": "setUniswapAddr", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -12528,18 +12758,18 @@ "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "vaultAddr", + "outputs": [ { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "sellOusdForUsdt", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -12558,39 +12788,17 @@ "type": "function" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "token", + "name": "_address", "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "rebaseOptIn", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" + "name": "UniswapUpdated", + "type": "event" }, { "anonymous": false, @@ -12631,6 +12839,32 @@ "type": "event" } ] + }, + "OracleRouter": { + "address": "0xBAe5888057Fb3be601Fb172873596DaE7EB701A8", + "abi": [ + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "price", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] } } } \ No newline at end of file diff --git a/dapp/network.rinkeby.json b/dapp/network.rinkeby.json index 98b7fdf5fa..c3ffb9b22c 100644 --- a/dapp/network.rinkeby.json +++ b/dapp/network.rinkeby.json @@ -3608,6 +3608,237 @@ } ] }, + "Flipper": { + "address": "0x856A20Ba8F0F60Ee87298182933eD4FCDf7abf9B", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithUsdt", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithDai", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claimGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdrawAll", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForDai", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithUsdc", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForUsdc", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isGovernor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForUsdt", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "rebaseOptIn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "PendingGovernorshipTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "GovernorshipTransferred", + "type": "event" + } + ] + }, "Governor": { "address": "0xa39d23bA9Aa6Bb842a2A7f90ac8c0075e53E6507", "abi": [ @@ -19399,7 +19630,7 @@ ] }, "VaultAdmin": { - "address": "0x7ebBc1eaF5843703F19DF5754334870DA8bc8491", + "address": "0x93662b49b557b08049ffc8Ebdd852bD8DB04FfCe", "abi": [ { "constant": false, @@ -19496,6 +19727,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDMint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -19556,27 +19808,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDRedeem", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": false, "inputs": [ @@ -19717,8 +19948,14 @@ }, { "constant": false, - "inputs": [], - "name": "claimGovernance", + "inputs": [ + { + "internalType": "address", + "name": "_strategyAddr", + "type": "address" + } + ], + "name": "withdrawAllFromStrategy", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -19726,38 +19963,26 @@ }, { "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_maxSupplyDiff", - "type": "uint256" - } - ], - "name": "setMaxSupplyDiff", + "inputs": [], + "name": "claimGovernance", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ - { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDMint", - "outputs": [ { "internalType": "uint256", - "name": "", + "name": "_maxSupplyDiff", "type": "uint256" } ], + "name": "setMaxSupplyDiff", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -19805,6 +20030,27 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDRedeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], @@ -19984,6 +20230,15 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [], + "name": "withdrawAllFromStrategies", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [ @@ -20360,7 +20615,7 @@ ] }, "VaultCore": { - "address": "0x1D6B56e17D08e83dc2198A61Cb5BC9744cF8D9fE", + "address": "0x24203812AcB90c75860db158c637C286259059ba", "abi": [ { "constant": true, @@ -21383,8 +21638,8 @@ } ] }, - "Flipper": { - "address": "0x856A20Ba8F0F60Ee87298182933eD4FCDf7abf9B", + "Buyback": { + "address": "0x37f91c38F57b382bf9A40b2640c998Ed172f5bdA", "abi": [ { "constant": true, @@ -21404,31 +21659,36 @@ { "constant": false, "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, { "internalType": "uint256", "name": "amount", "type": "uint256" } ], - "name": "buyOusdWithUsdt", + "name": "transferToken", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "uniswapAddr", + "outputs": [ { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "buyOusdWithDai", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -21443,22 +21703,7 @@ { "constant": false, "inputs": [], - "name": "withdrawAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "sellOusdForDai", + "name": "swap", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -21468,27 +21713,12 @@ "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "buyOusdWithUsdc", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "address", + "name": "_address", + "type": "address" } ], - "name": "sellOusdForUsdc", + "name": "setUniswapAddr", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -21510,18 +21740,18 @@ "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "vaultAddr", + "outputs": [ { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "sellOusdForUsdt", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -21540,39 +21770,17 @@ "type": "function" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "token", + "name": "_address", "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "withdraw", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "rebaseOptIn", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" + "name": "UniswapUpdated", + "type": "event" }, { "anonymous": false, @@ -21613,6 +21821,32 @@ "type": "event" } ] + }, + "OracleRouter": { + "address": "0x3D69B41fDd3b8f555Feb3974086dA9790A2fccAb", + "abi": [ + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "price", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ] } } } \ No newline at end of file diff --git a/dapp/prod.network.json b/dapp/prod.network.json index 12cb0e813b..c7acb9a17e 100644 --- a/dapp/prod.network.json +++ b/dapp/prod.network.json @@ -3608,6 +3608,237 @@ } ] }, + "Flipper": { + "address": "0xcecaD69d7D4Ed6D52eFcFA028aF8732F27e08F70", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithUsdt", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithDai", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "claimGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdrawAll", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForDai", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "buyOusdWithUsdc", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForUsdc", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isGovernor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sellOusdForUsdt", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "rebaseOptIn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "PendingGovernorshipTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "GovernorshipTransferred", + "type": "event" + } + ] + }, "Governor": { "address": "0x8e7bDFeCd1164C46ad51b58e49A611F954D23377", "abi": [ @@ -8276,54 +8507,48 @@ } ] }, - "Timelock": { - "address": "0x2693C0eCcb5734EBd3910E9c23a8039401a73c87", + "ThreePoolStrategy": { + "address": "0x9F2E2b1c5F6Ac748b61f07e88f912A1df33Dfe55", "abi": [ + { + "constant": false, + "inputs": [], + "name": "collectRewardToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": false, "inputs": [ { "internalType": "address", - "name": "target", + "name": "_asset", "type": "address" }, { - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "eta", - "type": "uint256" - } - ], - "name": "executeTransaction", - "outputs": [ - { - "internalType": "bytes", - "name": "", - "type": "bytes" + "internalType": "address", + "name": "_pToken", + "type": "address" } ], - "payable": true, - "stateMutability": "payable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "acceptAdmin", + "name": "setPTokenAddress", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -8331,32 +8556,23 @@ }, { "constant": true, - "inputs": [], - "name": "pendingAdmin", - "outputs": [ + "inputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ + "name": "assetToPToken", + "outputs": [ { "internalType": "address", - "name": "target", + "name": "", "type": "address" } ], - "name": "pauseDeposits", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -8364,55 +8580,49 @@ "inputs": [ { "internalType": "address", - "name": "target", + "name": "_asset", "type": "address" }, { "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "eta", + "name": "_amount", "type": "uint256" } ], - "name": "queueTransaction", + "name": "transferToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "rewardTokenAddress", "outputs": [ { - "internalType": "bytes32", + "internalType": "address", "name": "", - "type": "bytes32" + "type": "address" } ], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "vaultAddress", + "outputs": [ { "internalType": "address", - "name": "pendingAdmin_", + "name": "", "type": "address" } ], - "name": "setPendingAdmin", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -8420,31 +8630,16 @@ "inputs": [ { "internalType": "address", - "name": "target", + "name": "_asset", "type": "address" }, { "internalType": "uint256", - "name": "value", - "type": "uint256" - }, - { - "internalType": "string", - "name": "signature", - "type": "string" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - }, - { - "internalType": "uint256", - "name": "eta", + "name": "_amount", "type": "uint256" } ], - "name": "cancelTransaction", + "name": "deposit", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -8453,7 +8648,7 @@ { "constant": true, "inputs": [], - "name": "delay", + "name": "rewardLiquidationThreshold", "outputs": [ { "internalType": "uint256", @@ -8466,43 +8661,28 @@ "type": "function" }, { - "constant": true, + "constant": false, "inputs": [], - "name": "MAXIMUM_DELAY", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "name": "claimGovernance", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "constant": true, - "inputs": [], - "name": "MINIMUM_DELAY", - "outputs": [ + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "_asset", + "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "GRACE_PERIOD", + "name": "checkBalance", "outputs": [ { "internalType": "uint256", - "name": "", + "name": "balance", "type": "uint256" } ], @@ -8515,11 +8695,40 @@ "inputs": [ { "internalType": "address", - "name": "target", + "name": "_platformAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_vaultAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardTokenAddress", "type": "address" + }, + { + "internalType": "address[]", + "name": "_assets", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_pTokens", + "type": "address[]" } ], - "name": "unpauseDeposits", + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdrawAll", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -8530,11 +8739,26 @@ "inputs": [ { "internalType": "uint256", - "name": "delay_", + "name": "_assetIndex", "type": "uint256" } ], - "name": "setDelay", + "name": "removePToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardTokenAddress", + "type": "address" + } + ], + "name": "setRewardTokenAddress", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -8544,12 +8768,12 @@ "constant": true, "inputs": [ { - "internalType": "bytes32", - "name": "", - "type": "bytes32" + "internalType": "address", + "name": "_asset", + "type": "address" } ], - "name": "queuedTransactions", + "name": "supportsAsset", "outputs": [ { "internalType": "bool", @@ -8561,15 +8785,24 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [], + "name": "safeApproveAllTokens", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], - "name": "admin", + "name": "isGovernor", "outputs": [ { - "internalType": "address", + "internalType": "bool", "name": "", - "type": "address" + "type": "bool" } ], "payable": false, @@ -8577,107 +8810,146 @@ "type": "function" }, { + "constant": false, "inputs": [ - { - "internalType": "address", - "name": "admin_", - "type": "address" - }, { "internalType": "uint256", - "name": "delay_", + "name": "_threshold", "type": "uint256" } ], + "name": "setRewardLiquidationThreshold", + "outputs": [], "payable": false, "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "payable": true, - "stateMutability": "payable", - "type": "fallback" + "type": "function" }, { - "anonymous": false, + "constant": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "newAdmin", + "name": "_newGovernor", "type": "address" } ], - "name": "NewAdmin", - "type": "event" + "name": "transferGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, + "constant": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "newPendingAdmin", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "_asset", "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" } ], - "name": "NewPendingAdmin", - "type": "event" + "name": "withdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "platformAddress", + "outputs": [ { - "indexed": true, - "internalType": "uint256", - "name": "newDelay", - "type": "uint256" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "NewDelay", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, + "constant": false, + "inputs": [], + "name": "depositAll", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, "inputs": [ { - "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" + "internalType": "address", + "name": "_platformAddress", + "type": "address" }, { - "indexed": true, "internalType": "address", - "name": "target", + "name": "_vaultAddress", "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" + "internalType": "address", + "name": "_rewardTokenAddress", + "type": "address" }, { - "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" + "internalType": "address[]", + "name": "_assets", + "type": "address[]" + }, + { + "internalType": "address[]", + "name": "_pTokens", + "type": "address[]" + }, + { + "internalType": "address", + "name": "_crvGaugeAddress", + "type": "address" }, + { + "internalType": "address", + "name": "_crvMinterAddress", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ { "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "address", + "name": "recipient", + "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "eta", + "name": "amount", "type": "uint256" } ], - "name": "CancelTransaction", + "name": "RewardTokenCollected", "type": "event" }, { @@ -8685,42 +8957,62 @@ "inputs": [ { "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" + "internalType": "address", + "name": "_asset", + "type": "address" }, + { + "indexed": false, + "internalType": "address", + "name": "_pToken", + "type": "address" + } + ], + "name": "PTokenAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": true, "internalType": "address", - "name": "target", + "name": "_asset", "type": "address" }, { "indexed": false, - "internalType": "uint256", - "name": "value", - "type": "uint256" - }, + "internalType": "address", + "name": "_pToken", + "type": "address" + } + ], + "name": "PTokenRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" + "indexed": true, + "internalType": "address", + "name": "_asset", + "type": "address" }, { "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" + "internalType": "address", + "name": "_pToken", + "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "eta", + "name": "_amount", "type": "uint256" } ], - "name": "ExecuteTransaction", + "name": "Deposit", "type": "event" }, { @@ -8728,67 +9020,78 @@ "inputs": [ { "indexed": true, - "internalType": "bytes32", - "name": "txHash", - "type": "bytes32" + "internalType": "address", + "name": "_asset", + "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "target", + "name": "_pToken", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "value", + "name": "_amount", "type": "uint256" - }, + } + ], + "name": "Withdrawal", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "indexed": false, - "internalType": "string", - "name": "signature", - "type": "string" + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" }, { - "indexed": false, - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "PendingGovernorshipTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" }, { - "indexed": false, - "internalType": "uint256", - "name": "eta", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" } ], - "name": "QueueTransaction", + "name": "GovernorshipTransferred", "type": "event" } ] }, - "Vault": { - "address": "0x6bd6CC9605Ae43B424cB06363255b061A84DfFD3", + "ThreePoolStrategyProxy": { + "address": "0x3c5fe0a3922777343CBD67D3732FCdc9f2Fa6f2F", "abi": [ - { - "constant": false, - "inputs": [], - "name": "unpauseRebase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], - "name": "redeemFeeBps", + "name": "governor", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "payable": false, @@ -8796,37 +9099,16 @@ "type": "function" }, { - "constant": true, - "inputs": [], - "name": "governor", - "outputs": [ + "constant": false, + "inputs": [ { "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_strategyAddr", + "name": "newImplementation", "type": "address" } ], - "name": "harvest", - "outputs": [ - { - "internalType": "uint256[]", - "name": "", - "type": "uint256[]" - } - ], + "name": "upgradeTo", + "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" @@ -8836,25 +9118,25 @@ "inputs": [ { "internalType": "address", - "name": "_asset", + "name": "newImplementation", "type": "address" }, { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "transferToken", + "name": "upgradeToAndCall", "outputs": [], - "payable": false, - "stateMutability": "nonpayable", + "payable": true, + "stateMutability": "payable", "type": "function" }, { "constant": true, "inputs": [], - "name": "uniswapAddr", + "name": "implementation", "outputs": [ { "internalType": "address", @@ -8868,14 +9150,8 @@ }, { "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_addr", - "type": "address" - } - ], - "name": "removeStrategy", + "inputs": [], + "name": "claimGovernance", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -8884,12 +9160,12 @@ { "constant": true, "inputs": [], - "name": "vaultBuffer", + "name": "isGovernor", "outputs": [ { - "internalType": "uint256", + "internalType": "bool", "name": "", - "type": "uint256" + "type": "bool" } ], "payable": false, @@ -8897,24 +9173,28 @@ "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDRedeem", - "outputs": [ + "internalType": "address", + "name": "_logic", + "type": "address" + }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "_initGovernor", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "payable": false, - "stateMutability": "view", + "name": "initialize", + "outputs": [], + "payable": true, + "stateMutability": "payable", "type": "function" }, { @@ -8922,118 +9202,146 @@ "inputs": [ { "internalType": "address", - "name": "_priceProvider", + "name": "_newGovernor", "type": "address" } ], - "name": "setPriceProvider", + "name": "transferGovernance", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ { "internalType": "address", - "name": "_addr", + "name": "", "type": "address" } ], - "name": "approveStrategy", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": false, - "inputs": [], - "name": "pauseCapital", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "payable": true, + "stateMutability": "payable", + "type": "fallback" }, { - "constant": false, - "inputs": [], - "name": "harvest", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "_priceProvider", + "name": "previousGovernor", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "_ousd", + "name": "newGovernor", "type": "address" } ], - "name": "initialize", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "PendingGovernorshipTransfer", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "_asset", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", "type": "address" } ], - "name": "supportAsset", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, + "name": "GovernorshipTransferred", + "type": "event" + } + ] + }, + "Timelock": { + "address": "0x2693C0eCcb5734EBd3910E9c23a8039401a73c87", + "abi": [ { - "constant": true, - "inputs": [], - "name": "rebaseThreshold", - "outputs": [ + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, { "internalType": "uint256", - "name": "", + "name": "value", + "type": "uint256" + }, + { + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "rebasePaused", + "name": "executeTransaction", "outputs": [ { - "internalType": "bool", + "internalType": "bytes", "name": "", - "type": "bool" + "type": "bytes" } ], + "payable": true, + "stateMutability": "payable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "acceptAdmin", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [], - "name": "strategistAddr", + "name": "pendingAdmin", "outputs": [ { "internalType": "address", @@ -9045,49 +9353,60 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [], - "name": "claimGovernance", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": false, "inputs": [ { - "internalType": "uint256", - "name": "_maxSupplyDiff", - "type": "uint256" + "internalType": "address", + "name": "target", + "type": "address" } ], - "name": "setMaxSupplyDiff", + "name": "pauseDeposits", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ { - "internalType": "string", - "name": "symbol", - "type": "string" - } - ], - "name": "priceUSDMint", - "outputs": [ + "internalType": "address", + "name": "target", + "type": "address" + }, { "internalType": "uint256", - "name": "", + "name": "value", + "type": "uint256" + }, + { + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", "type": "uint256" } ], + "name": "queueTransaction", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -9095,11 +9414,11 @@ "inputs": [ { "internalType": "address", - "name": "_address", + "name": "pendingAdmin_", "type": "address" } ], - "name": "setStrategistAddr", + "name": "setPendingAdmin", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -9110,26 +9429,31 @@ "inputs": [ { "internalType": "address", - "name": "_strategyFromAddress", + "name": "target", "type": "address" }, { - "internalType": "address", - "name": "_strategyToAddress", - "type": "address" + "internalType": "uint256", + "name": "value", + "type": "uint256" }, { - "internalType": "address[]", - "name": "_assets", - "type": "address[]" + "internalType": "string", + "name": "signature", + "type": "string" }, { - "internalType": "uint256[]", - "name": "_amounts", - "type": "uint256[]" + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "eta", + "type": "uint256" } ], - "name": "reallocate", + "name": "cancelTransaction", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -9138,7 +9462,7 @@ { "constant": true, "inputs": [], - "name": "maxSupplyDiff", + "name": "delay", "outputs": [ { "internalType": "uint256", @@ -9151,33 +9475,24 @@ "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "MAXIMUM_DELAY", + "outputs": [ { "internalType": "uint256", - "name": "_vaultBuffer", + "name": "", "type": "uint256" } ], - "name": "setVaultBuffer", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "unpauseCapital", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], - "name": "autoAllocateThreshold", + "name": "MINIMUM_DELAY", "outputs": [ { "internalType": "uint256", @@ -9191,19 +9506,13 @@ }, { "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "assetDefaultStrategies", + "inputs": [], + "name": "GRACE_PERIOD", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "payable": false, @@ -9215,11 +9524,11 @@ "inputs": [ { "internalType": "address", - "name": "_address", + "name": "target", "type": "address" } ], - "name": "setUniswapAddr", + "name": "unpauseDeposits", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -9230,11 +9539,11 @@ "inputs": [ { "internalType": "uint256", - "name": "_threshold", + "name": "delay_", "type": "uint256" } ], - "name": "setAutoAllocateThreshold", + "name": "setDelay", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -9242,67 +9551,14 @@ }, { "constant": true, - "inputs": [], - "name": "priceProvider", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_threshold", - "type": "uint256" - } - ], - "name": "setRebaseThreshold", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, "inputs": [ { - "internalType": "address", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_strategy", - "type": "address" + "internalType": "bytes32", + "name": "", + "type": "bytes32" } ], - "name": "setAssetDefaultStrategy", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "pauseRebase", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "isGovernor", + "name": "queuedTransactions", "outputs": [ { "internalType": "bool", @@ -9314,30 +9570,15 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_newGovernor", - "type": "address" - } - ], - "name": "transferGovernance", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], - "name": "capitalPaused", + "name": "admin", "outputs": [ { - "internalType": "bool", + "internalType": "address", "name": "", - "type": "bool" + "type": "address" } ], "payable": false, @@ -9345,257 +9586,150 @@ "type": "function" }, { - "constant": false, "inputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, { "internalType": "uint256", - "name": "_redeemFeeBps", + "name": "delay_", "type": "uint256" } ], - "name": "setRedeemFeeBps", - "outputs": [], "payable": false, "stateMutability": "nonpayable", - "type": "function" + "type": "constructor" }, { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "newImpl", - "type": "address" - } - ], - "name": "setAdminImpl", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "payable": true, + "stateMutability": "payable", + "type": "fallback" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "_asset", + "name": "newAdmin", "type": "address" } ], - "name": "AssetSupported", + "name": "NewAdmin", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "_asset", - "type": "address" - }, - { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "_strategy", + "name": "newPendingAdmin", "type": "address" } ], - "name": "AssetDefaultStrategyUpdated", + "name": "NewPendingAdmin", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "_addr", - "type": "address" + "indexed": true, + "internalType": "uint256", + "name": "newDelay", + "type": "uint256" } ], - "name": "StrategyApproved", + "name": "NewDelay", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, + { + "indexed": true, "internalType": "address", - "name": "_addr", - "type": "address" - } - ], - "name": "StrategyRemoved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_addr", + "name": "target", "type": "address" }, { "indexed": false, "internalType": "uint256", - "name": "_value", + "name": "value", "type": "uint256" - } - ], - "name": "Mint", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { "indexed": false, - "internalType": "address", - "name": "_addr", - "type": "address" + "internalType": "string", + "name": "signature", + "type": "string" }, { "indexed": false, - "internalType": "uint256", - "name": "_value", - "type": "uint256" - } - ], - "name": "Redeem", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CapitalPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CapitalUnpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "RebasePaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "RebaseUnpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, { "indexed": false, "internalType": "uint256", - "name": "_vaultBuffer", + "name": "eta", "type": "uint256" } ], - "name": "VaultBufferUpdated", + "name": "CancelTransaction", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "_redeemFeeBps", - "type": "uint256" - } - ], - "name": "RedeemFeeUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "indexed": true, + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" + }, { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "_priceProvider", + "name": "target", "type": "address" - } - ], - "name": "PriceProviderUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_threshold", - "type": "uint256" - } - ], - "name": "AllocateThresholdUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { "indexed": false, "internalType": "uint256", - "name": "_threshold", + "name": "value", "type": "uint256" - } - ], - "name": "RebaseThresholdUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { "indexed": false, - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "UniswapUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "internalType": "string", + "name": "signature", + "type": "string" + }, { "indexed": false, - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "StrategistUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, { "indexed": false, "internalType": "uint256", - "name": "maxSupplyDiff", + "name": "eta", "type": "uint256" } ], - "name": "MaxSupplyDiffChanged", + "name": "ExecuteTransaction", "type": "event" }, { @@ -9603,43 +9737,48 @@ "inputs": [ { "indexed": true, - "internalType": "address", - "name": "previousGovernor", - "type": "address" + "internalType": "bytes32", + "name": "txHash", + "type": "bytes32" }, { "indexed": true, "internalType": "address", - "name": "newGovernor", + "name": "target", "type": "address" - } - ], - "name": "PendingGovernorshipTransfer", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, - "internalType": "address", - "name": "previousGovernor", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" }, { - "indexed": true, - "internalType": "address", - "name": "newGovernor", - "type": "address" + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "eta", + "type": "uint256" } ], - "name": "GovernorshipTransferred", + "name": "QueueTransaction", "type": "event" } ] }, - "VaultAdmin": { - "address": "0xb5f7E47Bc7D271b3df4824BDcFBB279a719F8Ae6", + "Vault": { + "address": "0x6bd6CC9605Ae43B424cB06363255b061A84DfFD3", "abi": [ { "constant": false, @@ -9665,21 +9804,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_basis", - "type": "uint256" - } - ], - "name": "setTrusteeFeeBps", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], @@ -9781,21 +9905,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": true, - "inputs": [], - "name": "trusteeFeeBps", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": true, "inputs": [ @@ -9817,21 +9926,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "setTrusteeAddress", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": false, "inputs": [ @@ -9881,18 +9975,23 @@ "type": "function" }, { - "constant": true, - "inputs": [], - "name": "trusteeAddress", - "outputs": [ + "constant": false, + "inputs": [ { "internalType": "address", - "name": "", + "name": "_priceProvider", + "type": "address" + }, + { + "internalType": "address", + "name": "_ousd", "type": "address" } ], + "name": "initialize", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -10508,57 +10607,6 @@ "name": "MaxSupplyDiffChanged", "type": "event" }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_yield", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_fee", - "type": "uint256" - } - ], - "name": "YieldDistribution", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_basis", - "type": "uint256" - } - ], - "name": "TrusteeFeeBpsChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_address", - "type": "address" - } - ], - "name": "TrusteeAddressChanged", - "type": "event" - }, { "anonymous": false, "inputs": [ @@ -10599,9 +10647,18 @@ } ] }, - "VaultCore": { - "address": "0x3e803eEA623eE4793f0f49790A813811da5249f4", + "VaultAdmin": { + "address": "0x8E55b527901BC88206a1cE5C292B2404bcb8F76D", "abi": [ + { + "constant": false, + "inputs": [], + "name": "unpauseRebase", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], @@ -10617,6 +10674,21 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_basis", + "type": "uint256" + } + ], + "name": "setTrusteeFeeBps", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], @@ -10633,18 +10705,24 @@ "type": "function" }, { - "constant": true, - "inputs": [], - "name": "uniswapAddr", - "outputs": [ + "constant": false, + "inputs": [ { "internalType": "address", - "name": "", + "name": "_strategyAddr", "type": "address" } ], + "name": "harvest", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { @@ -10659,14 +10737,9 @@ "internalType": "uint256", "name": "_amount", "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_minimumOusdAmount", - "type": "uint256" } ], - "name": "mint", + "name": "transferToken", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -10674,8 +10747,14 @@ }, { "constant": true, - "inputs": [], - "name": "vaultBuffer", + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "priceUSDMint", "outputs": [ { "internalType": "uint256", @@ -10690,27 +10769,42 @@ { "constant": true, "inputs": [], - "name": "trusteeFeeBps", + "name": "uniswapAddr", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "removeStrategy", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], - "name": "getAllAssets", + "name": "vaultBuffer", "outputs": [ { - "internalType": "address[]", + "internalType": "uint256", "name": "", - "type": "address[]" + "type": "uint256" } ], "payable": false, @@ -10720,7 +10814,7 @@ { "constant": true, "inputs": [], - "name": "getStrategyCount", + "name": "trusteeFeeBps", "outputs": [ { "internalType": "uint256", @@ -10732,6 +10826,69 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setTrusteeAddress", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_priceProvider", + "type": "address" + } + ], + "name": "setPriceProvider", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "approveStrategy", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pauseCapital", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "harvest", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], @@ -10747,6 +10904,21 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "supportAsset", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], @@ -10792,6 +10964,21 @@ "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_strategyAddr", + "type": "address" + } + ], + "name": "withdrawAllFromStrategy", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": false, "inputs": [], @@ -10802,41 +10989,80 @@ "type": "function" }, { - "constant": true, + "constant": false, "inputs": [ { - "internalType": "address", - "name": "_asset", - "type": "address" + "internalType": "uint256", + "name": "_maxSupplyDiff", + "type": "uint256" } ], - "name": "checkBalance", - "outputs": [ + "name": "setMaxSupplyDiff", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" + "internalType": "address", + "name": "_address", + "type": "address" } ], + "name": "setStrategistAddr", + "outputs": [], "payable": false, - "stateMutability": "view", + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_strategyFromAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_strategyToAddress", + "type": "address" + }, + { + "internalType": "address[]", + "name": "_assets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_amounts", + "type": "uint256[]" + } + ], + "name": "reallocate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [ { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" + "internalType": "address", + "name": "asset", + "type": "address" } ], - "name": "calculateRedeemOutputs", + "name": "priceUSDRedeem", "outputs": [ { - "internalType": "uint256[]", + "internalType": "uint256", "name": "", - "type": "uint256[]" + "type": "uint256" } ], "payable": false, @@ -10844,18 +11070,18 @@ "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "maxSupplyDiff", + "outputs": [ { "internalType": "uint256", - "name": "_minimumUnitAmount", + "name": "", "type": "uint256" } ], - "name": "redeemAll", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -10863,16 +11089,20 @@ "inputs": [ { "internalType": "uint256", - "name": "_amount", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_minimumUnitAmount", + "name": "_vaultBuffer", "type": "uint256" } ], - "name": "redeem", + "name": "setVaultBuffer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "unpauseCapital", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -10881,7 +11111,7 @@ { "constant": true, "inputs": [], - "name": "maxSupplyDiff", + "name": "autoAllocateThreshold", "outputs": [ { "internalType": "uint256", @@ -10898,46 +11128,120 @@ "inputs": [ { "internalType": "address", - "name": "_asset", + "name": "", "type": "address" } ], - "name": "isSupportedAsset", + "name": "assetDefaultStrategies", "outputs": [ { - "internalType": "bool", + "internalType": "address", "name": "", - "type": "bool" + "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "setUniswapAddr", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "setAutoAllocateThreshold", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], - "name": "autoAllocateThreshold", + "name": "priceProvider", "outputs": [ { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "setRebaseThreshold", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "address", + "name": "_strategy", + "type": "address" + } + ], + "name": "setAssetDefaultStrategy", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pauseRebase", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, { "constant": true, "inputs": [], - "name": "getAssetCount", + "name": "isGovernor", "outputs": [ { - "internalType": "uint256", + "internalType": "bool", "name": "", - "type": "uint256" + "type": "bool" } ], "payable": false, @@ -10945,20 +11249,38 @@ "type": "function" }, { - "constant": true, + "constant": false, + "inputs": [], + "name": "withdrawAllFromStrategies", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, "inputs": [ { "internalType": "address", - "name": "", + "name": "_newGovernor", "type": "address" } ], - "name": "assetDefaultStrategies", + "name": "transferGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "capitalPaused", "outputs": [ { - "internalType": "address", + "internalType": "bool", "name": "", - "type": "address" + "type": "bool" } ], "payable": false, @@ -10967,8 +11289,14 @@ }, { "constant": false, - "inputs": [], - "name": "allocate", + "inputs": [ + { + "internalType": "uint256", + "name": "_redeemFeeBps", + "type": "uint256" + } + ], + "name": "setRedeemFeeBps", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -10976,17 +11304,356 @@ }, { "constant": false, - "inputs": [], - "name": "rebase", + "inputs": [ + { + "internalType": "address", + "name": "newImpl", + "type": "address" + } + ], + "name": "setAdminImpl", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "AssetSupported", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_strategy", + "type": "address" + } + ], + "name": "AssetDefaultStrategyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "StrategyApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_addr", + "type": "address" + } + ], + "name": "StrategyRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_addr", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CapitalPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CapitalUnpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RebasePaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RebaseUnpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_vaultBuffer", + "type": "uint256" + } + ], + "name": "VaultBufferUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_redeemFeeBps", + "type": "uint256" + } + ], + "name": "RedeemFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_priceProvider", + "type": "address" + } + ], + "name": "PriceProviderUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "AllocateThresholdUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "RebaseThresholdUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "UniswapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "StrategistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxSupplyDiff", + "type": "uint256" + } + ], + "name": "MaxSupplyDiffChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_yield", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" + } + ], + "name": "YieldDistribution", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_basis", + "type": "uint256" + } + ], + "name": "TrusteeFeeBpsChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_address", + "type": "address" + } + ], + "name": "TrusteeAddressChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "PendingGovernorshipTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "GovernorshipTransferred", + "type": "event" + } + ] + }, + "VaultCore": { + "address": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "redeemFeeBps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], - "name": "priceProvider", + "name": "governor", "outputs": [ { "internalType": "address", @@ -11001,12 +11668,12 @@ { "constant": true, "inputs": [], - "name": "isGovernor", + "name": "uniswapAddr", "outputs": [ { - "internalType": "bool", + "internalType": "address", "name": "", - "type": "bool" + "type": "address" } ], "payable": false, @@ -11018,11 +11685,21 @@ "inputs": [ { "internalType": "address", - "name": "_newGovernor", + "name": "_asset", "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minimumOusdAmount", + "type": "uint256" } ], - "name": "transferGovernance", + "name": "mint", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -11031,11 +11708,11 @@ { "constant": true, "inputs": [], - "name": "totalValue", + "name": "vaultBuffer", "outputs": [ { "internalType": "uint256", - "name": "value", + "name": "", "type": "uint256" } ], @@ -11046,12 +11723,12 @@ { "constant": true, "inputs": [], - "name": "capitalPaused", + "name": "trusteeFeeBps", "outputs": [ { - "internalType": "bool", + "internalType": "uint256", "name": "", - "type": "bool" + "type": "uint256" } ], "payable": false, @@ -11059,377 +11736,241 @@ "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "getAllAssets", + "outputs": [ { "internalType": "address[]", - "name": "_assets", + "name": "", "type": "address[]" - }, - { - "internalType": "uint256[]", - "name": "_amounts", - "type": "uint256[]" - }, - { - "internalType": "uint256", - "name": "_minimumOusdAmount", - "type": "uint256" } ], - "name": "mintMultiple", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "constant": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "getStrategyCount", + "outputs": [ { - "internalType": "address", - "name": "newImpl", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "setAdminImpl", - "outputs": [], "payable": false, - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { - "payable": true, - "stateMutability": "payable", - "type": "fallback" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_asset", - "type": "address" - } - ], - "name": "AssetSupported", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_asset", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "_strategy", - "type": "address" - } - ], - "name": "AssetDefaultStrategyUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_addr", - "type": "address" - } - ], - "name": "StrategyApproved", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "trusteeAddress", + "outputs": [ { - "indexed": false, "internalType": "address", - "name": "_addr", + "name": "", "type": "address" } ], - "name": "StrategyRemoved", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_addr", - "type": "address" - }, + "constant": true, + "inputs": [], + "name": "rebaseThreshold", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "_value", + "name": "", "type": "uint256" } ], - "name": "Mint", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "_addr", - "type": "address" - }, + "constant": true, + "inputs": [], + "name": "rebasePaused", + "outputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "_value", - "type": "uint256" + "internalType": "bool", + "name": "", + "type": "bool" } ], - "name": "Redeem", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CapitalPaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "CapitalUnpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "RebasePaused", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, + "constant": true, "inputs": [], - "name": "RebaseUnpaused", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "strategistAddr", + "outputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "_vaultBuffer", - "type": "uint256" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "VaultBufferUpdated", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_redeemFeeBps", - "type": "uint256" - } - ], - "name": "RedeemFeeUpdated", - "type": "event" + "constant": false, + "inputs": [], + "name": "claimGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, + "constant": true, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "_priceProvider", - "type": "address" - } - ], - "name": "PriceProviderUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "_threshold", - "type": "uint256" + "name": "_asset", + "type": "address" } ], - "name": "AllocateThresholdUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "checkBalance", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "_threshold", + "name": "", "type": "uint256" } ], - "name": "RebaseThresholdUpdated", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, + "constant": true, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "_address", - "type": "address" + "internalType": "uint256", + "name": "_amount", + "type": "uint256" } ], - "name": "UniswapUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + "name": "calculateRedeemOutputs", + "outputs": [ { - "indexed": false, - "internalType": "address", - "name": "_address", - "type": "address" + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" } ], - "name": "StrategistUpdated", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, + "constant": false, "inputs": [ { - "indexed": false, "internalType": "uint256", - "name": "maxSupplyDiff", + "name": "_minimumUnitAmount", "type": "uint256" } ], - "name": "MaxSupplyDiffChanged", - "type": "event" + "name": "redeemAll", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, + "constant": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "indexed": false, "internalType": "uint256", - "name": "_yield", + "name": "_amount", "type": "uint256" }, { - "indexed": false, "internalType": "uint256", - "name": "_fee", + "name": "_minimumUnitAmount", "type": "uint256" } ], - "name": "YieldDistribution", - "type": "event" + "name": "redeem", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "constant": true, + "inputs": [], + "name": "maxSupplyDiff", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "_basis", + "name": "", "type": "uint256" } ], - "name": "TrusteeFeeBpsChanged", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, + "constant": true, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "_address", + "name": "_asset", "type": "address" } ], - "name": "TrusteeAddressChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousGovernor", - "type": "address" - }, + "name": "isSupportedAsset", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "newGovernor", - "type": "address" + "internalType": "bool", + "name": "", + "type": "bool" } ], - "name": "PendingGovernorshipTransfer", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousGovernor", - "type": "address" - }, + "constant": true, + "inputs": [], + "name": "autoAllocateThreshold", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "newGovernor", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "GovernorshipTransferred", - "type": "event" - } - ] - }, - "VaultProxy": { - "address": "0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70", - "abi": [ + "payable": false, + "stateMutability": "view", + "type": "function" + }, { "constant": true, "inputs": [], - "name": "governor", + "name": "getAssetCount", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "payable": false, @@ -11437,15 +11978,30 @@ "type": "function" }, { - "constant": false, + "constant": true, "inputs": [ { "internalType": "address", - "name": "newImplementation", + "name": "", "type": "address" } ], - "name": "upgradeTo", + "name": "assetDefaultStrategies", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "allocate", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -11453,33 +12009,37 @@ }, { "constant": false, - "inputs": [ + "inputs": [], + "name": "rebase", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "priceProvider", + "outputs": [ { "internalType": "address", - "name": "newImplementation", + "name": "", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "name": "upgradeToAndCall", - "outputs": [], - "payable": true, - "stateMutability": "payable", + "payable": false, + "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], - "name": "implementation", + "name": "isGovernor", "outputs": [ { - "internalType": "address", + "internalType": "bool", "name": "", - "type": "address" + "type": "bool" } ], "payable": false, @@ -11488,8 +12048,14 @@ }, { "constant": false, - "inputs": [], - "name": "claimGovernance", + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -11498,7 +12064,22 @@ { "constant": true, "inputs": [], - "name": "isGovernor", + "name": "totalValue", + "outputs": [ + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "capitalPaused", "outputs": [ { "internalType": "bool", @@ -11514,25 +12095,25 @@ "constant": false, "inputs": [ { - "internalType": "address", - "name": "_logic", - "type": "address" + "internalType": "address[]", + "name": "_assets", + "type": "address[]" }, { - "internalType": "address", - "name": "_initGovernor", - "type": "address" + "internalType": "uint256[]", + "name": "_amounts", + "type": "uint256[]" }, { - "internalType": "bytes", - "name": "_data", - "type": "bytes" + "internalType": "uint256", + "name": "_minimumOusdAmount", + "type": "uint256" } ], - "name": "initialize", + "name": "mintMultiple", "outputs": [], - "payable": true, - "stateMutability": "payable", + "payable": false, + "stateMutability": "nonpayable", "type": "function" }, { @@ -11540,31 +12121,16 @@ "inputs": [ { "internalType": "address", - "name": "_newGovernor", + "name": "newImpl", "type": "address" } ], - "name": "transferGovernance", + "name": "setAdminImpl", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, - { - "constant": true, - "inputs": [], - "name": "admin", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "payable": true, "stateMutability": "payable", @@ -11574,218 +12140,275 @@ "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "implementation", + "name": "_asset", "type": "address" } ], - "name": "Upgraded", + "name": "AssetSupported", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "previousGovernor", + "name": "_asset", "type": "address" }, { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newGovernor", + "name": "_strategy", "type": "address" } ], - "name": "PendingGovernorshipTransfer", + "name": "AssetDefaultStrategyUpdated", "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "previousGovernor", - "type": "address" - }, - { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "newGovernor", + "name": "_addr", "type": "address" } ], - "name": "GovernorshipTransferred", + "name": "StrategyApproved", "type": "event" - } - ] - }, - "ThreePoolStrategyProxy": { - "address": "0x3c5fe0a3922777343CBD67D3732FCdc9f2Fa6f2F", - "abi": [ + }, { - "constant": true, - "inputs": [], - "name": "governor", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": false, "internalType": "address", - "name": "", + "name": "_addr", "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "StrategyRemoved", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "newImplementation", + "name": "_addr", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_value", + "type": "uint256" } ], - "name": "upgradeTo", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "Mint", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "newImplementation", + "name": "_addr", "type": "address" }, { - "internalType": "bytes", - "name": "data", - "type": "bytes" + "indexed": false, + "internalType": "uint256", + "name": "_value", + "type": "uint256" } ], - "name": "upgradeToAndCall", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" + "name": "Redeem", + "type": "event" }, { - "constant": true, + "anonymous": false, "inputs": [], - "name": "implementation", - "outputs": [ + "name": "CapitalPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "CapitalUnpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RebasePaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "RebaseUnpaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_vaultBuffer", + "type": "uint256" + } + ], + "name": "VaultBufferUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_redeemFeeBps", + "type": "uint256" + } + ], + "name": "RedeemFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": false, "internalType": "address", - "name": "", + "name": "_priceProvider", "type": "address" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "PriceProviderUpdated", + "type": "event" }, { - "constant": false, - "inputs": [], - "name": "claimGovernance", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" + } + ], + "name": "AllocateThresholdUpdated", + "type": "event" }, { - "constant": true, - "inputs": [], - "name": "isGovernor", - "outputs": [ + "anonymous": false, + "inputs": [ { - "internalType": "bool", - "name": "", - "type": "bool" + "indexed": false, + "internalType": "uint256", + "name": "_threshold", + "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "RebaseThresholdUpdated", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "_logic", + "name": "_address", "type": "address" - }, + } + ], + "name": "UniswapUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": false, "internalType": "address", - "name": "_initGovernor", + "name": "_address", "type": "address" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" } ], - "name": "initialize", - "outputs": [], - "payable": true, - "stateMutability": "payable", - "type": "function" + "name": "StrategistUpdated", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { - "internalType": "address", - "name": "_newGovernor", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "maxSupplyDiff", + "type": "uint256" } ], - "name": "transferGovernance", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "MaxSupplyDiffChanged", + "type": "event" }, { - "constant": true, - "inputs": [], - "name": "admin", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": false, "internalType": "address", - "name": "", + "name": "_to", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_yield", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_fee", + "type": "uint256" } ], - "payable": false, - "stateMutability": "view", - "type": "function" + "name": "YieldDistribution", + "type": "event" }, { - "payable": true, - "stateMutability": "payable", - "type": "fallback" + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_basis", + "type": "uint256" + } + ], + "name": "TrusteeFeeBpsChanged", + "type": "event" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "implementation", + "name": "_address", "type": "address" } ], - "name": "Upgraded", + "name": "TrusteeAddressChanged", "type": "event" }, { @@ -11828,18 +12451,9 @@ } ] }, - "ThreePoolStrategy": { - "address": "0x9F2E2b1c5F6Ac748b61f07e88f912A1df33Dfe55", + "VaultProxy": { + "address": "0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70", "abi": [ - { - "constant": false, - "inputs": [], - "name": "collectRewardToken", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, { "constant": true, "inputs": [], @@ -11860,81 +12474,40 @@ "inputs": [ { "internalType": "address", - "name": "_asset", - "type": "address" - }, - { - "internalType": "address", - "name": "_pToken", + "name": "newImplementation", "type": "address" } ], - "name": "setPTokenAddress", + "name": "upgradeTo", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "name": "assetToPToken", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": false, "inputs": [ { "internalType": "address", - "name": "_asset", + "name": "newImplementation", "type": "address" }, { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "name": "transferToken", + "name": "upgradeToAndCall", "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "rewardTokenAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", + "payable": true, + "stateMutability": "payable", "type": "function" }, { "constant": true, "inputs": [], - "name": "vaultAddress", + "name": "implementation", "outputs": [ { "internalType": "address", @@ -11946,41 +12519,6 @@ "stateMutability": "view", "type": "function" }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "_asset", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_amount", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "rewardLiquidationThreshold", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, { "constant": false, "inputs": [], @@ -11992,19 +12530,13 @@ }, { "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_asset", - "type": "address" - } - ], - "name": "checkBalance", + "inputs": [], + "name": "isGovernor", "outputs": [ { - "internalType": "uint256", - "name": "balance", - "type": "uint256" + "internalType": "bool", + "name": "", + "type": "bool" } ], "payable": false, @@ -12016,58 +12548,24 @@ "inputs": [ { "internalType": "address", - "name": "_platformAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_vaultAddress", + "name": "_logic", "type": "address" }, { "internalType": "address", - "name": "_rewardTokenAddress", + "name": "_initGovernor", "type": "address" }, { - "internalType": "address[]", - "name": "_assets", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "_pTokens", - "type": "address[]" + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], "name": "initialize", "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "withdrawAll", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "_assetIndex", - "type": "uint256" - } - ], - "name": "removePToken", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", + "payable": true, + "stateMutability": "payable", "type": "function" }, { @@ -12075,41 +12573,11 @@ "inputs": [ { "internalType": "address", - "name": "_rewardTokenAddress", - "type": "address" - } - ], - "name": "setRewardTokenAddress", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "address", - "name": "_asset", - "type": "address" - } - ], - "name": "supportsAsset", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "safeApproveAllTokens", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -12118,12 +12586,12 @@ { "constant": true, "inputs": [], - "name": "isGovernor", + "name": "admin", "outputs": [ { - "internalType": "bool", + "internalType": "address", "name": "", - "type": "bool" + "type": "address" } ], "payable": false, @@ -12131,55 +12599,96 @@ "type": "function" }, { - "constant": false, + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "anonymous": false, "inputs": [ { - "internalType": "uint256", - "name": "_threshold", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "name": "setRewardLiquidationThreshold", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "_newGovernor", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", "type": "address" } ], - "name": "transferGovernance", - "outputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" + "name": "PendingGovernorshipTransfer", + "type": "event" }, { - "constant": false, + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "_recipient", + "name": "previousGovernor", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "_asset", + "name": "newGovernor", + "type": "address" + } + ], + "name": "GovernorshipTransferred", + "type": "event" + } + ] + }, + "Buyback": { + "address": "0x7294CD3C3eb4097b03E1A61EB2AD280D3dD265e6", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "token", "type": "address" }, { "internalType": "uint256", - "name": "_amount", + "name": "amount", "type": "uint256" } ], - "name": "withdraw", + "name": "transferToken", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -12188,7 +12697,7 @@ { "constant": true, "inputs": [], - "name": "platformAddress", + "name": "uniswapAddr", "outputs": [ { "internalType": "address", @@ -12203,7 +12712,16 @@ { "constant": false, "inputs": [], - "name": "depositAll", + "name": "claimGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "swap", "outputs": [], "payable": false, "stateMutability": "nonpayable", @@ -12214,126 +12732,72 @@ "inputs": [ { "internalType": "address", - "name": "_platformAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_vaultAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_rewardTokenAddress", - "type": "address" - }, - { - "internalType": "address[]", - "name": "_assets", - "type": "address[]" - }, - { - "internalType": "address[]", - "name": "_pTokens", - "type": "address[]" - }, - { - "internalType": "address", - "name": "_crvGaugeAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "_crvMinterAddress", + "name": "_address", "type": "address" } ], - "name": "initialize", + "name": "setUniswapAddr", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "recipient", - "type": "address" - }, + "constant": true, + "inputs": [], + "name": "isGovernor", + "outputs": [ { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" + "internalType": "bool", + "name": "", + "type": "bool" } ], - "name": "RewardTokenCollected", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_asset", - "type": "address" - }, + "constant": true, + "inputs": [], + "name": "vaultAddr", + "outputs": [ { - "indexed": false, "internalType": "address", - "name": "_pToken", + "name": "", "type": "address" } ], - "name": "PTokenAdded", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, + "constant": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "_asset", - "type": "address" - }, - { - "indexed": false, "internalType": "address", - "name": "_pToken", + "name": "_newGovernor", "type": "address" } ], - "name": "PTokenRemoved", - "type": "event" + "name": "transferGovernance", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" }, { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "_asset", - "type": "address" - }, { "indexed": false, "internalType": "address", - "name": "_pToken", + "name": "_address", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" } ], - "name": "Deposit", + "name": "UniswapUpdated", "type": "event" }, { @@ -12342,23 +12806,17 @@ { "indexed": true, "internalType": "address", - "name": "_asset", + "name": "previousGovernor", "type": "address" }, { - "indexed": false, + "indexed": true, "internalType": "address", - "name": "_pToken", + "name": "newGovernor", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "_amount", - "type": "uint256" } ], - "name": "Withdrawal", + "name": "PendingGovernorshipTransfer", "type": "event" }, { @@ -12377,27 +12835,34 @@ "type": "address" } ], - "name": "PendingGovernorshipTransfer", + "name": "GovernorshipTransferred", "type": "event" - }, + } + ] + }, + "OracleRouter": { + "address": "0xBAe5888057Fb3be601Fb172873596DaE7EB701A8", + "abi": [ { - "anonymous": false, + "constant": true, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousGovernor", + "name": "asset", "type": "address" - }, + } + ], + "name": "price", + "outputs": [ { - "indexed": true, - "internalType": "address", - "name": "newGovernor", - "type": "address" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "GovernorshipTransferred", - "type": "event" + "payable": false, + "stateMutability": "view", + "type": "function" } ] }