diff --git a/contracts/deployments/mainnet/.migrations.json b/contracts/deployments/mainnet/.migrations.json index 8a7602bf2b..fb5fbe8fad 100644 --- a/contracts/deployments/mainnet/.migrations.json +++ b/contracts/deployments/mainnet/.migrations.json @@ -15,5 +15,6 @@ "015_flipper": 1613166856, "016_chainlink_and_buyback": 1616629649, "017_3pool_strategy_update": 1621303419, - "018_upgrade_governor": 1624425881 + "018_upgrade_governor": 1624425881, + "019_resolution_and_savings": 1625266338 } \ No newline at end of file diff --git a/contracts/deployments/mainnet/OUSD.json b/contracts/deployments/mainnet/OUSD.json index 71d472284d..9a1ed10e5d 100644 --- a/contracts/deployments/mainnet/OUSD.json +++ b/contracts/deployments/mainnet/OUSD.json @@ -1,5 +1,5 @@ { - "address": "0x9d6975591E777D95Eef3bCC2a727846DA25d7083", + "address": "0x23DCc0Cc5F08b9D85daF8d29490c7f74a655b359", "abi": [ { "constant": true, @@ -652,42 +652,42 @@ "type": "event" } ], - "transactionHash": "0xfd274acab483ce50a68a19d70dacde9cc1d3b32fd0b4799deeb5f35961913850", + "transactionHash": "0xa6e64eaffdaefdfb3bebcbf7446ea5edacd3966ffbeab258244ad5f5a6a41754", "receipt": { "to": null, "from": "0x71F78361537A6f7B6818e7A760c8bC0146D93f50", - "contractAddress": "0x9d6975591E777D95Eef3bCC2a727846DA25d7083", - "transactionIndex": 76, - "gasUsed": "1977489", - "logsBloom": "0x00000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000820000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000010000000000000000000010000000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4c525ead587466aedf883dfbbbf39d82164e8e43cdf66b0982b87e710ec3279e", - "transactionHash": "0xfd274acab483ce50a68a19d70dacde9cc1d3b32fd0b4799deeb5f35961913850", + "contractAddress": "0x23DCc0Cc5F08b9D85daF8d29490c7f74a655b359", + "transactionIndex": 39, + "gasUsed": "1995223", + "logsBloom": "0x00000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000020000000000000000000800000000800000000000000000000000000004000000000000000000000000000000000000000000000000000000200000000000000000000000000000008000000000000000000000000000000000000000000000000000000010000000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x76a4e09fc99449fe2e832b73a5fb5dd00aeb03bf8b1b03716a5e6ecbfb24779e", + "transactionHash": "0xa6e64eaffdaefdfb3bebcbf7446ea5edacd3966ffbeab258244ad5f5a6a41754", "logs": [ { - "transactionIndex": 76, - "blockNumber": 11779355, - "transactionHash": "0xfd274acab483ce50a68a19d70dacde9cc1d3b32fd0b4799deeb5f35961913850", - "address": "0x9d6975591E777D95Eef3bCC2a727846DA25d7083", + "transactionIndex": 39, + "blockNumber": 12750980, + "transactionHash": "0xa6e64eaffdaefdfb3bebcbf7446ea5edacd3966ffbeab258244ad5f5a6a41754", + "address": "0x23DCc0Cc5F08b9D85daF8d29490c7f74a655b359", "topics": [ "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x00000000000000000000000071f78361537a6f7b6818e7a760c8bc0146d93f50" ], "data": "0x", - "logIndex": 135, - "blockHash": "0x4c525ead587466aedf883dfbbbf39d82164e8e43cdf66b0982b87e710ec3279e" + "logIndex": 20, + "blockHash": "0x76a4e09fc99449fe2e832b73a5fb5dd00aeb03bf8b1b03716a5e6ecbfb24779e" } ], - "blockNumber": 11779355, - "cumulativeGasUsed": "6572210", + "blockNumber": 12750980, + "cumulativeGasUsed": "3587874", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "c3af786fe12b6b771320281cb59e3482", - "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"string\",\"name\":\"_nameArg\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbolArg\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_vaultAddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasingCredits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newTotalSupply\",\"type\":\"uint256\"}],\"name\":\"changeSupply\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rebaseState\",\"outputs\":[{\"internalType\":\"enum OUSD.RebaseOptions\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonRebasingCreditsPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasingCreditsPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebaseOptOut\",\"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\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nonRebasingSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebaseOptIn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"creditsBalanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rebasingCredits\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rebasingCreditsPerToken\",\"type\":\"uint256\"}],\"name\":\"TotalSupplyUpdated\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allowance(address,address)\":{\"details\":\"Function to check the _amount of tokens that an owner has allowed to a _spender.\",\"params\":{\"_owner\":\"The address which owns the funds.\",\"_spender\":\"The address which will spend the funds.\"},\"return\":\"The number of tokens still available for the _spender.\"},\"approve(address,uint256)\":{\"details\":\"Approve the passed address to spend the specified _amount of tokens on behalf of msg.sender. This method is included for ERC20 compatibility. increaseAllowance and decreaseAllowance should be used instead. Changing an allowance with this method brings the risk that someone may transfer both the old and the new allowance - if they are both greater than zero - if a transfer transaction is mined before the later approve() call is mined.\",\"params\":{\"_spender\":\"The address which will spend the funds.\",\"_value\":\"The _amount of tokens to be spent.\"}},\"balanceOf(address)\":{\"details\":\"Gets the balance of the specified address.\",\"params\":{\"_account\":\"Address to query the balance of.\"},\"return\":\"A uint256 representing the _amount of base units owned by the specified address.\"},\"burn(address,uint256)\":{\"details\":\"Burns tokens, decreasing totalSupply.\"},\"changeSupply(uint256)\":{\"details\":\"Modify the supply without minting new tokens. This uses a change in the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\",\"params\":{\"_newTotalSupply\":\"New total supply of OUSD.\"},\"return\":\"uint256 representing the new total supply.\"},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"creditsBalanceOf(address)\":{\"details\":\"Gets the credits balance of the specified address.\",\"params\":{\"_account\":\"The address to query the balance of.\"},\"return\":\"(uint256, uint256) Credit balance and credits per token of the address\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). * Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. * NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Decrease the _amount of tokens that an owner has allowed to a _spender.\",\"params\":{\"_spender\":\"The address which will spend the funds.\",\"_subtractedValue\":\"The _amount of tokens to decrease the allowance by.\"}},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Increase the _amount of tokens that an owner has allowed to a _spender. This method should be used instead of approve() to avoid the double approval vulnerability described above.\",\"params\":{\"_addedValue\":\"The _amount of tokens to increase the allowance by.\",\"_spender\":\"The address which will spend the funds.\"}},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"mint(address,uint256)\":{\"details\":\"Mints new tokens, increasing totalSupply.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"rebaseOptIn()\":{\"details\":\"Add a contract address to the non rebasing exception list. I.e. the address's balance will be part of rebases so the account will be exposed to upside and downside.\"},\"rebaseOptOut()\":{\"details\":\"Remove a contract address to the non rebasing exception list.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"return\":\"The total supply of OUSD.\"},\"transfer(address,uint256)\":{\"details\":\"Transfer tokens to a specified address.\",\"params\":{\"_to\":\"the address to transfer to.\",\"_value\":\"the _amount to be transferred.\"},\"return\":\"true on success.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"Transfer tokens from one address to another.\",\"params\":{\"_from\":\"The address you want to send tokens from.\",\"_to\":\"The address you want to transfer to.\",\"_value\":\"The _amount of tokens to be transferred.\"}},\"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\":{},\"notice\":\"NOTE that this is an ERC20 token but the invariant that the sum of balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the rebasing design. Any integrations with OUSD should be aware.\"}},\"settings\":{\"compilationTarget\":{\"contracts/token/OUSD.sol\":\"OUSD\"},\"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/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/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/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\"}},\"version\":1}", - "bytecode": "0x6080604052609c80546001600160a01b031916905562000028336001600160e01b036200008116565b6200003b6001600160e01b036200009416565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000a8565b6000805160206200230c83398151915255565b6000805160206200230c8339815191525490565b61225480620000b86000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80635d36b19011610104578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105e5578063e696393a14610613578063f51b0fd41461061b578063f9854bfc14610623576101cf565b8063a9059cbb14610583578063c2376dff146105af578063c7af3352146105b7578063d38bfff4146105bf576101cf565b806370a08231116100de57806370a08231146104fd57806395d89b41146105235780639dc29fac1461052b578063a457c2d714610557576101cf565b80635d36b190146104c7578063609350cd146104cf5780636691cb3d146104f5576101cf565b8063313ce567116101715780633eaaf86b1161014b5780633eaaf86b1461044157806340c10f1914610449578063430bf08a14610475578063456ee2861461047d576101cf565b8063313ce567146103da57806339509351146103f857806339a7919f14610424576101cf565b8063095ea7b3116101ad578063095ea7b3146103385780630c340a241461037857806318160ddd1461039c57806323b872dd146103a4576101cf565b806306fdde03146101d4578063077f224a14610251578063077f22b71461031e575b600080fd5b6101dc610662565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61031c6004803603606081101561026757600080fd5b81019060208101813564010000000081111561028257600080fd5b82018360208201111561029457600080fd5b803590602001918460018302840111640100000000831117156102b657600080fd5b9193909290916020810190356401000000008111156102d457600080fd5b8201836020820111156102e657600080fd5b8035906020019184600183028401116401000000008311171561030857600080fd5b9193509150356001600160a01b03166106f9565b005b610326610896565b60408051918252519081900360200190f35b6103646004803603604081101561034e57600080fd5b506001600160a01b03813516906020013561089c565b604080519115158252519081900360200190f35b610380610903565b604080516001600160a01b039092168252519081900360200190f35b610326610912565b610364600480360360608110156103ba57600080fd5b506001600160a01b03813581169160208101359091169060400135610918565b6103e2610a73565b6040805160ff9092168252519081900360200190f35b6103646004803603604081101561040e57600080fd5b506001600160a01b038135169060200135610a7c565b61031c6004803603602081101561043a57600080fd5b5035610b15565b610326610d8f565b61031c6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610d95565b610380610dfc565b6104a36004803603602081101561049357600080fd5b50356001600160a01b0316610e0b565b604051808260028111156104b357fe5b60ff16815260200191505060405180910390f35b61031c610e20565b610326600480360360208110156104e557600080fd5b50356001600160a01b0316610e82565b610326610e94565b6103266004803603602081101561051357600080fd5b50356001600160a01b0316610e9a565b6101dc610ef8565b61031c6004803603604081101561054157600080fd5b506001600160a01b038135169060200135610f59565b6103646004803603604081101561056d57600080fd5b506001600160a01b038135169060200135610fbc565b6103646004803603604081101561059957600080fd5b506001600160a01b0381351690602001356110ab565b61031c6111a2565b6103646112cd565b61031c600480360360208110156105d557600080fd5b50356001600160a01b03166112f0565b610326600480360360408110156105fb57600080fd5b506001600160a01b038135811691602001351661139c565b6103266113c7565b61031c6113cd565b6106496004803603602081101561063957600080fd5b50356001600160a01b0316611534565b6040805192835260208301919091528051918290030190f35b60978054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b820191906000526020600020905b8154815290600101906020018083116106d157829003601f168201915b505050505090505b90565b6107016112cd565b610752576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b600054610100900460ff168061076b575061076b611561565b80610779575060005460ff16155b6107b45760405162461bcd60e51b815260040180806020018281038252602e8152602001806121a2602e913960400191505060405180910390fd5b600054610100900460ff161580156107df576000805460ff1961ff0019909116610100171660011790555b61085586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525060129250611567915050565b670de0b6b3a7640000609f55609c80546001600160a01b0319166001600160a01b038416179055801561088e576000805461ff00191690555b505050505050565b609e5481565b336000818152609b602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090d6115a7565b905090565b609a5490565b60006001600160a01b038316610970576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61097984610e9a565b8211156109cd576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b6001600160a01b0384166000908152609b60209081526040808320338452909152902054610a01908363ffffffff6115cc16565b6001600160a01b0385166000908152609b60209081526040808320338452909152902055610a30848484611615565b826001600160a01b0316846001600160a01b03166000805160206121d0833981519152846040518082815260200191505060405180910390a35060019392505050565b60995460ff1690565b336000908152609b602090815260408083206001600160a01b0386168452909152812054610ab0908363ffffffff6117ad16565b336000818152609b602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b609c546001600160a01b03163314610b6e576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b60008051602061216183398151915280546002811415610bc6576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556000609a5411610c21576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420696e637265617365203020737570706c790000000000000000604482015290519081900360640190fd5b82609a541415610c7757609a54609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a1610d87565b6001600160801b038311610c8b5782610c94565b6001600160801b035b609a81905560a054610cbe91610caf9163ffffffff6115cc16565b609e549063ffffffff61180716565b609f819055610d14576040805162461bcd60e51b815260206004820152601860248201527f496e76616c6964206368616e676520696e20737570706c790000000000000000604482015290519081900360640190fd5b610d3d60a054610d31609f54609e5461180790919063ffffffff16565b9063ffffffff6117ad16565b609a819055609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a15b506001905550565b609a5481565b609c546001600160a01b03163314610dee576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df8828261183c565b5050565b609c546001600160a01b031681565b60a26020526000908152604090205460ff1681565b610e28611a25565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b81526004018080602001828103825260308152602001806121f06030913960400191505060405180910390fd5b610e8033611a4a565b565b60a16020526000908152604090205481565b609f5481565b6001600160a01b0381166000908152609d6020526040812054610ebf57506000610ef3565b610ef0610ecb83611af8565b6001600160a01b0384166000908152609d60205260409020549063ffffffff61180716565b90505b919050565b60988054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b609c546001600160a01b03163314610fb2576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df88282611b3e565b336000908152609b602090815260408083206001600160a01b038616845290915281205480831061101057336000908152609b602090815260408083206001600160a01b0388168452909152812055611045565b611020818463ffffffff6115cc16565b336000908152609b602090815260408083206001600160a01b03891684529091529020555b336000818152609b602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60006001600160a01b038316611103576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61110c33610e9a565b821115611160576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b61116b338484611615565b6040805183815290516001600160a01b0385169133916000805160206121d08339815191529181900360200190a350600192915050565b600080516020612161833981519152805460028114156111fa576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561120733611d88565b15611259576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e7420686173206e6f74206f7074656420696e0000000000000000604482015290519081900360640190fd5b61127461126533610e9a565b60a0549063ffffffff6117ad16565b60a055609f5433600090815260a16020908152604080832093909355609d90522054609e546112a89163ffffffff6115cc16565b609e555033600090815260a260205260409020805460ff191660019081179091559055565b60006112d76115a7565b6001600160a01b0316336001600160a01b031614905090565b6112f86112cd565b611349576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61135281611df4565b806001600160a01b03166113646115a7565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b6001600160a01b039182166000908152609b6020908152604080832093909416825291909152205490565b60a05481565b60008051602061216183398151915280546002811415611425576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561143233611d88565b611483576040805162461bcd60e51b815260206004820152601960248201527f4163636f756e7420686173206e6f74206f70746564206f757400000000000000604482015290519081900360640190fd5b60006114bf61149133611af8565b609f54336000908152609d60205260409020546114b39163ffffffff611e1816565b9063ffffffff611e7116565b90506114dc6114cd33610e9a565b60a0549063ffffffff6115cc16565b60a055336000908152609d60205260409020819055609e54611504908263ffffffff6117ad16565b609e55505033600090815260a260209081526040808320805460ff1916600217905560a190915281205560019055565b6001600160a01b0381166000908152609d6020526040812054819061155884611af8565b91509150915091565b303b1590565b825161157a9060979060208601906120c8565b50815161158e9060989060208501906120c8565b506099805460ff191660ff929092169190911790555050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600061160e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611eb3565b9392505050565b600061162083611d88565b9050600061162d85611d88565b9050600061164a61163d86611af8565b859063ffffffff611f4a16565b9050600061166761165a88611af8565b869063ffffffff611f4a16565b90506116d8816040518060400160405280601f81526020017f5472616e7366657220616d6f756e7420657863656564732062616c616e636500815250609d60008b6001600160a01b03166001600160a01b0316815260200190815260200160002054611eb39092919063ffffffff16565b6001600160a01b038089166000908152609d6020526040808220939093559088168152205461170d908363ffffffff6117ad16565b6001600160a01b0387166000908152609d6020526040902055838015611731575082155b156117675760a054611749908663ffffffff6117ad16565b60a055609e5461175f908263ffffffff6115cc16565b609e556117a4565b831580156117725750825b156117a45760a05461178a908663ffffffff6115cc16565b60a055609e546117a0908363ffffffff6117ad16565b609e555b50505050505050565b60008282018381101561160e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008061182284670de0b6b3a764000063ffffffff611e1816565b9050611834818463ffffffff611e7116565b949350505050565b60008051602061216183398151915280546002811415611894576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b0384166118f3576040805162461bcd60e51b815260206004820152601860248201527f4d696e7420746f20746865207a65726f20616464726573730000000000000000604482015290519081900360640190fd5b60006118fe85611d88565b9050600061190e61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915061193a908263ffffffff6117ad16565b6001600160a01b0387166000908152609d602052604090205581156119745760a05461196c908663ffffffff6117ad16565b60a05561198b565b609e54611987908263ffffffff6117ad16565b609e555b609a5461199e908663ffffffff6117ad16565b609a8190556001600160801b03116119ea576040805162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b604482015290519081900360640190fd5b6040805186815290516001600160a01b038816916000916000805160206121d08339815191529181900360200190a350506001825550505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116611aa5576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316611ab76115a7565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3611af581611f5f565b50565b6001600160a01b038116600090815260a1602052604081205415611b3557506001600160a01b038116600090815260a16020526040902054610ef3565b50609f54610ef3565b60008051602061216183398151915280546002811415611b96576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b038416611bf5576040805162461bcd60e51b815260206004820152601a60248201527f4275726e2066726f6d20746865207a65726f2061646472657373000000000000604482015290519081900360640190fd5b82611bff57611d7f565b6000611c0a85611d88565b90506000611c1a61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915080821480611c4657508160018203145b15611c69576001600160a01b0387166000908152609d6020526040812055611cfe565b81811115611cb8576001600160a01b0387166000908152609d6020526040902054611c9a908363ffffffff6115cc16565b6001600160a01b0388166000908152609d6020526040902055611cfe565b6040805162461bcd60e51b815260206004820152601660248201527552656d6f766520657863656564732062616c616e636560501b604482015290519081900360640190fd5b8215611d1f5760a054611d17908763ffffffff6115cc16565b60a055611d36565b609e54611d32908363ffffffff6115cc16565b609e555b609a54611d49908763ffffffff6115cc16565b609a556040805187815290516000916001600160a01b038a16916000805160206121d08339815191529181900360200190a35050505b50600190555050565b600080611d9483611f83565b9050808015611dc757506001600160a01b038316600090815260a2602052604081205460ff166002811115611dc557fe5b145b15611dd557611dd583611fbc565b50506001600160a01b0316600090815260a16020526040902054151590565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600082611e27575060006108fd565b82820282848281611e3457fe5b041461160e5760405162461bcd60e51b81526004018080602001828103825260218152602001806121816021913960400191505060405180910390fd5b600061160e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612035565b60008184841115611f425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f07578181015183820152602001611eef565b50505050905090810190601f168015611f345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061160e8383670de0b6b3a764000061209a565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611834575050151592915050565b6001600160a01b038116600090815260a16020526040902054611af557609f546001600160a01b038216600090815260a1602052604090205561200161126582610e9a565b60a0556001600160a01b0381166000908152609d6020526040902054609e5461202f9163ffffffff6115cc16565b609e5550565b600081836120845760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611f07578181015183820152602001611eef565b50600083858161209057fe5b0495945050505050565b6000806120ad858563ffffffff611e1816565b90506120bf818463ffffffff611e7116565b95945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061210957805160ff1916838001178555612136565b82800160010185558215612136579182015b8281111561213657825182559160200191906001019061211b565b50612142929150612146565b5090565b6106f691905b80821115612142576000815560010161214c56fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158205227783b0c43cba340cfbfe748686c3a494c001c4b18954f2047eaf486aec56b64736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80635d36b19011610104578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105e5578063e696393a14610613578063f51b0fd41461061b578063f9854bfc14610623576101cf565b8063a9059cbb14610583578063c2376dff146105af578063c7af3352146105b7578063d38bfff4146105bf576101cf565b806370a08231116100de57806370a08231146104fd57806395d89b41146105235780639dc29fac1461052b578063a457c2d714610557576101cf565b80635d36b190146104c7578063609350cd146104cf5780636691cb3d146104f5576101cf565b8063313ce567116101715780633eaaf86b1161014b5780633eaaf86b1461044157806340c10f1914610449578063430bf08a14610475578063456ee2861461047d576101cf565b8063313ce567146103da57806339509351146103f857806339a7919f14610424576101cf565b8063095ea7b3116101ad578063095ea7b3146103385780630c340a241461037857806318160ddd1461039c57806323b872dd146103a4576101cf565b806306fdde03146101d4578063077f224a14610251578063077f22b71461031e575b600080fd5b6101dc610662565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61031c6004803603606081101561026757600080fd5b81019060208101813564010000000081111561028257600080fd5b82018360208201111561029457600080fd5b803590602001918460018302840111640100000000831117156102b657600080fd5b9193909290916020810190356401000000008111156102d457600080fd5b8201836020820111156102e657600080fd5b8035906020019184600183028401116401000000008311171561030857600080fd5b9193509150356001600160a01b03166106f9565b005b610326610896565b60408051918252519081900360200190f35b6103646004803603604081101561034e57600080fd5b506001600160a01b03813516906020013561089c565b604080519115158252519081900360200190f35b610380610903565b604080516001600160a01b039092168252519081900360200190f35b610326610912565b610364600480360360608110156103ba57600080fd5b506001600160a01b03813581169160208101359091169060400135610918565b6103e2610a73565b6040805160ff9092168252519081900360200190f35b6103646004803603604081101561040e57600080fd5b506001600160a01b038135169060200135610a7c565b61031c6004803603602081101561043a57600080fd5b5035610b15565b610326610d8f565b61031c6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610d95565b610380610dfc565b6104a36004803603602081101561049357600080fd5b50356001600160a01b0316610e0b565b604051808260028111156104b357fe5b60ff16815260200191505060405180910390f35b61031c610e20565b610326600480360360208110156104e557600080fd5b50356001600160a01b0316610e82565b610326610e94565b6103266004803603602081101561051357600080fd5b50356001600160a01b0316610e9a565b6101dc610ef8565b61031c6004803603604081101561054157600080fd5b506001600160a01b038135169060200135610f59565b6103646004803603604081101561056d57600080fd5b506001600160a01b038135169060200135610fbc565b6103646004803603604081101561059957600080fd5b506001600160a01b0381351690602001356110ab565b61031c6111a2565b6103646112cd565b61031c600480360360208110156105d557600080fd5b50356001600160a01b03166112f0565b610326600480360360408110156105fb57600080fd5b506001600160a01b038135811691602001351661139c565b6103266113c7565b61031c6113cd565b6106496004803603602081101561063957600080fd5b50356001600160a01b0316611534565b6040805192835260208301919091528051918290030190f35b60978054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b820191906000526020600020905b8154815290600101906020018083116106d157829003601f168201915b505050505090505b90565b6107016112cd565b610752576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b600054610100900460ff168061076b575061076b611561565b80610779575060005460ff16155b6107b45760405162461bcd60e51b815260040180806020018281038252602e8152602001806121a2602e913960400191505060405180910390fd5b600054610100900460ff161580156107df576000805460ff1961ff0019909116610100171660011790555b61085586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525060129250611567915050565b670de0b6b3a7640000609f55609c80546001600160a01b0319166001600160a01b038416179055801561088e576000805461ff00191690555b505050505050565b609e5481565b336000818152609b602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090d6115a7565b905090565b609a5490565b60006001600160a01b038316610970576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61097984610e9a565b8211156109cd576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b6001600160a01b0384166000908152609b60209081526040808320338452909152902054610a01908363ffffffff6115cc16565b6001600160a01b0385166000908152609b60209081526040808320338452909152902055610a30848484611615565b826001600160a01b0316846001600160a01b03166000805160206121d0833981519152846040518082815260200191505060405180910390a35060019392505050565b60995460ff1690565b336000908152609b602090815260408083206001600160a01b0386168452909152812054610ab0908363ffffffff6117ad16565b336000818152609b602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b609c546001600160a01b03163314610b6e576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b60008051602061216183398151915280546002811415610bc6576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556000609a5411610c21576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420696e637265617365203020737570706c790000000000000000604482015290519081900360640190fd5b82609a541415610c7757609a54609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a1610d87565b6001600160801b038311610c8b5782610c94565b6001600160801b035b609a81905560a054610cbe91610caf9163ffffffff6115cc16565b609e549063ffffffff61180716565b609f819055610d14576040805162461bcd60e51b815260206004820152601860248201527f496e76616c6964206368616e676520696e20737570706c790000000000000000604482015290519081900360640190fd5b610d3d60a054610d31609f54609e5461180790919063ffffffff16565b9063ffffffff6117ad16565b609a819055609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a15b506001905550565b609a5481565b609c546001600160a01b03163314610dee576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df8828261183c565b5050565b609c546001600160a01b031681565b60a26020526000908152604090205460ff1681565b610e28611a25565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b81526004018080602001828103825260308152602001806121f06030913960400191505060405180910390fd5b610e8033611a4a565b565b60a16020526000908152604090205481565b609f5481565b6001600160a01b0381166000908152609d6020526040812054610ebf57506000610ef3565b610ef0610ecb83611af8565b6001600160a01b0384166000908152609d60205260409020549063ffffffff61180716565b90505b919050565b60988054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b609c546001600160a01b03163314610fb2576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df88282611b3e565b336000908152609b602090815260408083206001600160a01b038616845290915281205480831061101057336000908152609b602090815260408083206001600160a01b0388168452909152812055611045565b611020818463ffffffff6115cc16565b336000908152609b602090815260408083206001600160a01b03891684529091529020555b336000818152609b602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60006001600160a01b038316611103576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61110c33610e9a565b821115611160576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b61116b338484611615565b6040805183815290516001600160a01b0385169133916000805160206121d08339815191529181900360200190a350600192915050565b600080516020612161833981519152805460028114156111fa576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561120733611d88565b15611259576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e7420686173206e6f74206f7074656420696e0000000000000000604482015290519081900360640190fd5b61127461126533610e9a565b60a0549063ffffffff6117ad16565b60a055609f5433600090815260a16020908152604080832093909355609d90522054609e546112a89163ffffffff6115cc16565b609e555033600090815260a260205260409020805460ff191660019081179091559055565b60006112d76115a7565b6001600160a01b0316336001600160a01b031614905090565b6112f86112cd565b611349576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61135281611df4565b806001600160a01b03166113646115a7565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b6001600160a01b039182166000908152609b6020908152604080832093909416825291909152205490565b60a05481565b60008051602061216183398151915280546002811415611425576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561143233611d88565b611483576040805162461bcd60e51b815260206004820152601960248201527f4163636f756e7420686173206e6f74206f70746564206f757400000000000000604482015290519081900360640190fd5b60006114bf61149133611af8565b609f54336000908152609d60205260409020546114b39163ffffffff611e1816565b9063ffffffff611e7116565b90506114dc6114cd33610e9a565b60a0549063ffffffff6115cc16565b60a055336000908152609d60205260409020819055609e54611504908263ffffffff6117ad16565b609e55505033600090815260a260209081526040808320805460ff1916600217905560a190915281205560019055565b6001600160a01b0381166000908152609d6020526040812054819061155884611af8565b91509150915091565b303b1590565b825161157a9060979060208601906120c8565b50815161158e9060989060208501906120c8565b506099805460ff191660ff929092169190911790555050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600061160e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611eb3565b9392505050565b600061162083611d88565b9050600061162d85611d88565b9050600061164a61163d86611af8565b859063ffffffff611f4a16565b9050600061166761165a88611af8565b869063ffffffff611f4a16565b90506116d8816040518060400160405280601f81526020017f5472616e7366657220616d6f756e7420657863656564732062616c616e636500815250609d60008b6001600160a01b03166001600160a01b0316815260200190815260200160002054611eb39092919063ffffffff16565b6001600160a01b038089166000908152609d6020526040808220939093559088168152205461170d908363ffffffff6117ad16565b6001600160a01b0387166000908152609d6020526040902055838015611731575082155b156117675760a054611749908663ffffffff6117ad16565b60a055609e5461175f908263ffffffff6115cc16565b609e556117a4565b831580156117725750825b156117a45760a05461178a908663ffffffff6115cc16565b60a055609e546117a0908363ffffffff6117ad16565b609e555b50505050505050565b60008282018381101561160e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008061182284670de0b6b3a764000063ffffffff611e1816565b9050611834818463ffffffff611e7116565b949350505050565b60008051602061216183398151915280546002811415611894576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b0384166118f3576040805162461bcd60e51b815260206004820152601860248201527f4d696e7420746f20746865207a65726f20616464726573730000000000000000604482015290519081900360640190fd5b60006118fe85611d88565b9050600061190e61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915061193a908263ffffffff6117ad16565b6001600160a01b0387166000908152609d602052604090205581156119745760a05461196c908663ffffffff6117ad16565b60a05561198b565b609e54611987908263ffffffff6117ad16565b609e555b609a5461199e908663ffffffff6117ad16565b609a8190556001600160801b03116119ea576040805162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b604482015290519081900360640190fd5b6040805186815290516001600160a01b038816916000916000805160206121d08339815191529181900360200190a350506001825550505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116611aa5576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316611ab76115a7565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3611af581611f5f565b50565b6001600160a01b038116600090815260a1602052604081205415611b3557506001600160a01b038116600090815260a16020526040902054610ef3565b50609f54610ef3565b60008051602061216183398151915280546002811415611b96576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b038416611bf5576040805162461bcd60e51b815260206004820152601a60248201527f4275726e2066726f6d20746865207a65726f2061646472657373000000000000604482015290519081900360640190fd5b82611bff57611d7f565b6000611c0a85611d88565b90506000611c1a61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915080821480611c4657508160018203145b15611c69576001600160a01b0387166000908152609d6020526040812055611cfe565b81811115611cb8576001600160a01b0387166000908152609d6020526040902054611c9a908363ffffffff6115cc16565b6001600160a01b0388166000908152609d6020526040902055611cfe565b6040805162461bcd60e51b815260206004820152601660248201527552656d6f766520657863656564732062616c616e636560501b604482015290519081900360640190fd5b8215611d1f5760a054611d17908763ffffffff6115cc16565b60a055611d36565b609e54611d32908363ffffffff6115cc16565b609e555b609a54611d49908763ffffffff6115cc16565b609a556040805187815290516000916001600160a01b038a16916000805160206121d08339815191529181900360200190a35050505b50600190555050565b600080611d9483611f83565b9050808015611dc757506001600160a01b038316600090815260a2602052604081205460ff166002811115611dc557fe5b145b15611dd557611dd583611fbc565b50506001600160a01b0316600090815260a16020526040902054151590565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600082611e27575060006108fd565b82820282848281611e3457fe5b041461160e5760405162461bcd60e51b81526004018080602001828103825260218152602001806121816021913960400191505060405180910390fd5b600061160e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612035565b60008184841115611f425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f07578181015183820152602001611eef565b50505050905090810190601f168015611f345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061160e8383670de0b6b3a764000061209a565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611834575050151592915050565b6001600160a01b038116600090815260a16020526040902054611af557609f546001600160a01b038216600090815260a1602052604090205561200161126582610e9a565b60a0556001600160a01b0381166000908152609d6020526040902054609e5461202f9163ffffffff6115cc16565b609e5550565b600081836120845760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611f07578181015183820152602001611eef565b50600083858161209057fe5b0495945050505050565b6000806120ad858563ffffffff611e1816565b90506120bf818463ffffffff611e7116565b95945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061210957805160ff1916838001178555612136565b82800160010185558215612136579182015b8281111561213657825182559160200191906001019061211b565b50612142929150612146565b5090565b6106f691905b80821115612142576000815560010161214c56fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158205227783b0c43cba340cfbfe748686c3a494c001c4b18954f2047eaf486aec56b64736f6c634300050b0032", + "solcInputHash": "c2ea476b4aec8b6a8c5cdeb6adf2172f", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"string\",\"name\":\"_nameArg\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbolArg\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_vaultAddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasingCredits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newTotalSupply\",\"type\":\"uint256\"}],\"name\":\"changeSupply\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rebaseState\",\"outputs\":[{\"internalType\":\"enum OUSD.RebaseOptions\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonRebasingCreditsPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasingCreditsPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebaseOptOut\",\"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\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nonRebasingSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebaseOptIn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"creditsBalanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rebasingCredits\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rebasingCreditsPerToken\",\"type\":\"uint256\"}],\"name\":\"TotalSupplyUpdated\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allowance(address,address)\":{\"details\":\"Function to check the _amount of tokens that an owner has allowed to a _spender.\",\"params\":{\"_owner\":\"The address which owns the funds.\",\"_spender\":\"The address which will spend the funds.\"},\"return\":\"The number of tokens still available for the _spender.\"},\"approve(address,uint256)\":{\"details\":\"Approve the passed address to spend the specified _amount of tokens on behalf of msg.sender. This method is included for ERC20 compatibility. increaseAllowance and decreaseAllowance should be used instead. Changing an allowance with this method brings the risk that someone may transfer both the old and the new allowance - if they are both greater than zero - if a transfer transaction is mined before the later approve() call is mined.\",\"params\":{\"_spender\":\"The address which will spend the funds.\",\"_value\":\"The _amount of tokens to be spent.\"}},\"balanceOf(address)\":{\"details\":\"Gets the balance of the specified address.\",\"params\":{\"_account\":\"Address to query the balance of.\"},\"return\":\"A uint256 representing the _amount of base units owned by the specified address.\"},\"burn(address,uint256)\":{\"details\":\"Burns tokens, decreasing totalSupply.\"},\"changeSupply(uint256)\":{\"details\":\"Modify the supply without minting new tokens. This uses a change in the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\",\"params\":{\"_newTotalSupply\":\"New total supply of OUSD.\"},\"return\":\"uint256 representing the new total supply.\"},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"creditsBalanceOf(address)\":{\"details\":\"Gets the credits balance of the specified address.\",\"params\":{\"_account\":\"The address to query the balance of.\"},\"return\":\"(uint256, uint256) Credit balance and credits per token of the address\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). * Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. * NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Decrease the _amount of tokens that an owner has allowed to a _spender.\",\"params\":{\"_spender\":\"The address which will spend the funds.\",\"_subtractedValue\":\"The _amount of tokens to decrease the allowance by.\"}},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Increase the _amount of tokens that an owner has allowed to a _spender. This method should be used instead of approve() to avoid the double approval vulnerability described above.\",\"params\":{\"_addedValue\":\"The _amount of tokens to increase the allowance by.\",\"_spender\":\"The address which will spend the funds.\"}},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"mint(address,uint256)\":{\"details\":\"Mints new tokens, increasing totalSupply.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"rebaseOptIn()\":{\"details\":\"Add a contract address to the non rebasing exception list. I.e. the address's balance will be part of rebases so the account will be exposed to upside and downside.\"},\"rebaseOptOut()\":{\"details\":\"Remove a contract address to the non rebasing exception list.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"return\":\"The total supply of OUSD.\"},\"transfer(address,uint256)\":{\"details\":\"Transfer tokens to a specified address.\",\"params\":{\"_to\":\"the address to transfer to.\",\"_value\":\"the _amount to be transferred.\"},\"return\":\"true on success.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"Transfer tokens from one address to another.\",\"params\":{\"_from\":\"The address you want to send tokens from.\",\"_to\":\"The address you want to transfer to.\",\"_value\":\"The _amount of tokens to be transferred.\"}},\"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\":{},\"notice\":\"NOTE that this is an ERC20 token but the invariant that the sum of balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the rebasing design. Any integrations with OUSD should be aware.\"}},\"settings\":{\"compilationTarget\":{\"contracts/token/OUSD.sol\":\"OUSD\"},\"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/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/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 if (_creditBalances[_account] == 0) {\\n // Since there is no existing balance, we can directly set to\\n // high resolution, and do not have to do any other bookkeeping\\n nonRebasingCreditsPerToken[_account] = 1e27;\\n } else {\\n // Migrate an existing account:\\n\\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(\\n _creditBalances[_account]\\n );\\n }\\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\":\"0x24b5da93d2279b02336983588dada1fecd3360b5df7074d83f2a79170f4216df\"},\"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\"}},\"version\":1}", + "bytecode": "0x6080604052609c80546001600160a01b031916905562000028336001600160e01b036200008116565b6200003b6001600160e01b036200009416565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000a8565b6000805160206200235583398151915255565b600080516020620023558339815191525490565b61229d80620000b86000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80635d36b19011610104578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105e5578063e696393a14610613578063f51b0fd41461061b578063f9854bfc14610623576101cf565b8063a9059cbb14610583578063c2376dff146105af578063c7af3352146105b7578063d38bfff4146105bf576101cf565b806370a08231116100de57806370a08231146104fd57806395d89b41146105235780639dc29fac1461052b578063a457c2d714610557576101cf565b80635d36b190146104c7578063609350cd146104cf5780636691cb3d146104f5576101cf565b8063313ce567116101715780633eaaf86b1161014b5780633eaaf86b1461044157806340c10f1914610449578063430bf08a14610475578063456ee2861461047d576101cf565b8063313ce567146103da57806339509351146103f857806339a7919f14610424576101cf565b8063095ea7b3116101ad578063095ea7b3146103385780630c340a241461037857806318160ddd1461039c57806323b872dd146103a4576101cf565b806306fdde03146101d4578063077f224a14610251578063077f22b71461031e575b600080fd5b6101dc610662565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61031c6004803603606081101561026757600080fd5b81019060208101813564010000000081111561028257600080fd5b82018360208201111561029457600080fd5b803590602001918460018302840111640100000000831117156102b657600080fd5b9193909290916020810190356401000000008111156102d457600080fd5b8201836020820111156102e657600080fd5b8035906020019184600183028401116401000000008311171561030857600080fd5b9193509150356001600160a01b03166106f9565b005b610326610896565b60408051918252519081900360200190f35b6103646004803603604081101561034e57600080fd5b506001600160a01b03813516906020013561089c565b604080519115158252519081900360200190f35b610380610903565b604080516001600160a01b039092168252519081900360200190f35b610326610912565b610364600480360360608110156103ba57600080fd5b506001600160a01b03813581169160208101359091169060400135610918565b6103e2610a73565b6040805160ff9092168252519081900360200190f35b6103646004803603604081101561040e57600080fd5b506001600160a01b038135169060200135610a7c565b61031c6004803603602081101561043a57600080fd5b5035610b15565b610326610d8f565b61031c6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610d95565b610380610dfc565b6104a36004803603602081101561049357600080fd5b50356001600160a01b0316610e0b565b604051808260028111156104b357fe5b60ff16815260200191505060405180910390f35b61031c610e20565b610326600480360360208110156104e557600080fd5b50356001600160a01b0316610e82565b610326610e94565b6103266004803603602081101561051357600080fd5b50356001600160a01b0316610e9a565b6101dc610ef8565b61031c6004803603604081101561054157600080fd5b506001600160a01b038135169060200135610f59565b6103646004803603604081101561056d57600080fd5b506001600160a01b038135169060200135610fbc565b6103646004803603604081101561059957600080fd5b506001600160a01b0381351690602001356110ab565b61031c6111a2565b6103646112cd565b61031c600480360360208110156105d557600080fd5b50356001600160a01b03166112f0565b610326600480360360408110156105fb57600080fd5b506001600160a01b038135811691602001351661139c565b6103266113c7565b61031c6113cd565b6106496004803603602081101561063957600080fd5b50356001600160a01b0316611534565b6040805192835260208301919091528051918290030190f35b60978054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b820191906000526020600020905b8154815290600101906020018083116106d157829003601f168201915b505050505090505b90565b6107016112cd565b610752576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b600054610100900460ff168061076b575061076b611561565b80610779575060005460ff16155b6107b45760405162461bcd60e51b815260040180806020018281038252602e8152602001806121eb602e913960400191505060405180910390fd5b600054610100900460ff161580156107df576000805460ff1961ff0019909116610100171660011790555b61085586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525060129250611567915050565b670de0b6b3a7640000609f55609c80546001600160a01b0319166001600160a01b038416179055801561088e576000805461ff00191690555b505050505050565b609e5481565b336000818152609b602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090d6115a7565b905090565b609a5490565b60006001600160a01b038316610970576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61097984610e9a565b8211156109cd576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b6001600160a01b0384166000908152609b60209081526040808320338452909152902054610a01908363ffffffff6115cc16565b6001600160a01b0385166000908152609b60209081526040808320338452909152902055610a30848484611615565b826001600160a01b0316846001600160a01b0316600080516020612219833981519152846040518082815260200191505060405180910390a35060019392505050565b60995460ff1690565b336000908152609b602090815260408083206001600160a01b0386168452909152812054610ab0908363ffffffff6117ad16565b336000818152609b602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b609c546001600160a01b03163314610b6e576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b6000805160206121aa83398151915280546002811415610bc6576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556000609a5411610c21576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420696e637265617365203020737570706c790000000000000000604482015290519081900360640190fd5b82609a541415610c7757609a54609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a1610d87565b6001600160801b038311610c8b5782610c94565b6001600160801b035b609a81905560a054610cbe91610caf9163ffffffff6115cc16565b609e549063ffffffff61180716565b609f819055610d14576040805162461bcd60e51b815260206004820152601860248201527f496e76616c6964206368616e676520696e20737570706c790000000000000000604482015290519081900360640190fd5b610d3d60a054610d31609f54609e5461180790919063ffffffff16565b9063ffffffff6117ad16565b609a819055609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a15b506001905550565b609a5481565b609c546001600160a01b03163314610dee576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df8828261183c565b5050565b609c546001600160a01b031681565b60a26020526000908152604090205460ff1681565b610e28611a25565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b81526004018080602001828103825260308152602001806122396030913960400191505060405180910390fd5b610e8033611a4a565b565b60a16020526000908152604090205481565b609f5481565b6001600160a01b0381166000908152609d6020526040812054610ebf57506000610ef3565b610ef0610ecb83611af8565b6001600160a01b0384166000908152609d60205260409020549063ffffffff61180716565b90505b919050565b60988054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b609c546001600160a01b03163314610fb2576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df88282611b3e565b336000908152609b602090815260408083206001600160a01b038616845290915281205480831061101057336000908152609b602090815260408083206001600160a01b0388168452909152812055611045565b611020818463ffffffff6115cc16565b336000908152609b602090815260408083206001600160a01b03891684529091529020555b336000818152609b602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60006001600160a01b038316611103576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61110c33610e9a565b821115611160576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b61116b338484611615565b6040805183815290516001600160a01b0385169133916000805160206122198339815191529181900360200190a350600192915050565b6000805160206121aa833981519152805460028114156111fa576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561120733611d88565b15611259576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e7420686173206e6f74206f7074656420696e0000000000000000604482015290519081900360640190fd5b61127461126533610e9a565b60a0549063ffffffff6117ad16565b60a055609f5433600090815260a16020908152604080832093909355609d90522054609e546112a89163ffffffff6115cc16565b609e555033600090815260a260205260409020805460ff191660019081179091559055565b60006112d76115a7565b6001600160a01b0316336001600160a01b031614905090565b6112f86112cd565b611349576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61135281611df4565b806001600160a01b03166113646115a7565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b6001600160a01b039182166000908152609b6020908152604080832093909416825291909152205490565b60a05481565b6000805160206121aa83398151915280546002811415611425576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561143233611d88565b611483576040805162461bcd60e51b815260206004820152601960248201527f4163636f756e7420686173206e6f74206f70746564206f757400000000000000604482015290519081900360640190fd5b60006114bf61149133611af8565b609f54336000908152609d60205260409020546114b39163ffffffff611e1816565b9063ffffffff611e7116565b90506114dc6114cd33610e9a565b60a0549063ffffffff6115cc16565b60a055336000908152609d60205260409020819055609e54611504908263ffffffff6117ad16565b609e55505033600090815260a260209081526040808320805460ff1916600217905560a190915281205560019055565b6001600160a01b0381166000908152609d6020526040812054819061155884611af8565b91509150915091565b303b1590565b825161157a906097906020860190612111565b50815161158e906098906020850190612111565b506099805460ff191660ff929092169190911790555050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600061160e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611eb3565b9392505050565b600061162083611d88565b9050600061162d85611d88565b9050600061164a61163d86611af8565b859063ffffffff611f4a16565b9050600061166761165a88611af8565b869063ffffffff611f4a16565b90506116d8816040518060400160405280601f81526020017f5472616e7366657220616d6f756e7420657863656564732062616c616e636500815250609d60008b6001600160a01b03166001600160a01b0316815260200190815260200160002054611eb39092919063ffffffff16565b6001600160a01b038089166000908152609d6020526040808220939093559088168152205461170d908363ffffffff6117ad16565b6001600160a01b0387166000908152609d6020526040902055838015611731575082155b156117675760a054611749908663ffffffff6117ad16565b60a055609e5461175f908263ffffffff6115cc16565b609e556117a4565b831580156117725750825b156117a45760a05461178a908663ffffffff6115cc16565b60a055609e546117a0908363ffffffff6117ad16565b609e555b50505050505050565b60008282018381101561160e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008061182284670de0b6b3a764000063ffffffff611e1816565b9050611834818463ffffffff611e7116565b949350505050565b6000805160206121aa83398151915280546002811415611894576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b0384166118f3576040805162461bcd60e51b815260206004820152601860248201527f4d696e7420746f20746865207a65726f20616464726573730000000000000000604482015290519081900360640190fd5b60006118fe85611d88565b9050600061190e61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915061193a908263ffffffff6117ad16565b6001600160a01b0387166000908152609d602052604090205581156119745760a05461196c908663ffffffff6117ad16565b60a05561198b565b609e54611987908263ffffffff6117ad16565b609e555b609a5461199e908663ffffffff6117ad16565b609a8190556001600160801b03116119ea576040805162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b604482015290519081900360640190fd5b6040805186815290516001600160a01b038816916000916000805160206122198339815191529181900360200190a350506001825550505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116611aa5576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316611ab76115a7565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3611af581611f5f565b50565b6001600160a01b038116600090815260a1602052604081205415611b3557506001600160a01b038116600090815260a16020526040902054610ef3565b50609f54610ef3565b6000805160206121aa83398151915280546002811415611b96576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b038416611bf5576040805162461bcd60e51b815260206004820152601a60248201527f4275726e2066726f6d20746865207a65726f2061646472657373000000000000604482015290519081900360640190fd5b82611bff57611d7f565b6000611c0a85611d88565b90506000611c1a61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915080821480611c4657508160018203145b15611c69576001600160a01b0387166000908152609d6020526040812055611cfe565b81811115611cb8576001600160a01b0387166000908152609d6020526040902054611c9a908363ffffffff6115cc16565b6001600160a01b0388166000908152609d6020526040902055611cfe565b6040805162461bcd60e51b815260206004820152601660248201527552656d6f766520657863656564732062616c616e636560501b604482015290519081900360640190fd5b8215611d1f5760a054611d17908763ffffffff6115cc16565b60a055611d36565b609e54611d32908363ffffffff6115cc16565b609e555b609a54611d49908763ffffffff6115cc16565b609a556040805187815290516000916001600160a01b038a16916000805160206122198339815191529181900360200190a35050505b50600190555050565b600080611d9483611f83565b9050808015611dc757506001600160a01b038316600090815260a2602052604081205460ff166002811115611dc557fe5b145b15611dd557611dd583611fbc565b50506001600160a01b0316600090815260a16020526040902054151590565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600082611e27575060006108fd565b82820282848281611e3457fe5b041461160e5760405162461bcd60e51b81526004018080602001828103825260218152602001806121ca6021913960400191505060405180910390fd5b600061160e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061207e565b60008184841115611f425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f07578181015183820152602001611eef565b50505050905090810190601f168015611f345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061160e8383670de0b6b3a76400006120e3565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611834575050151592915050565b6001600160a01b038116600090815260a16020526040902054611af5576001600160a01b0381166000908152609d6020526040902054612022576001600160a01b038116600090815260a1602052604090206b033b2e3c9fd0803ce80000009055611af5565b609f546001600160a01b038216600090815260a1602052604090205561204a61126582610e9a565b60a0556001600160a01b0381166000908152609d6020526040902054609e546120789163ffffffff6115cc16565b609e5550565b600081836120cd5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611f07578181015183820152602001611eef565b5060008385816120d957fe5b0495945050505050565b6000806120f6858563ffffffff611e1816565b9050612108818463ffffffff611e7116565b95945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061215257805160ff191683800117855561217f565b8280016001018555821561217f579182015b8281111561217f578251825591602001919060010190612164565b5061218b92915061218f565b5090565b6106f691905b8082111561218b576000815560010161219556fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820cd6d1104ba3da6a25fe62bc6f9a1a33a9dda54786ec6f85e49ec318bf70a0c5664736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80635d36b19011610104578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105e5578063e696393a14610613578063f51b0fd41461061b578063f9854bfc14610623576101cf565b8063a9059cbb14610583578063c2376dff146105af578063c7af3352146105b7578063d38bfff4146105bf576101cf565b806370a08231116100de57806370a08231146104fd57806395d89b41146105235780639dc29fac1461052b578063a457c2d714610557576101cf565b80635d36b190146104c7578063609350cd146104cf5780636691cb3d146104f5576101cf565b8063313ce567116101715780633eaaf86b1161014b5780633eaaf86b1461044157806340c10f1914610449578063430bf08a14610475578063456ee2861461047d576101cf565b8063313ce567146103da57806339509351146103f857806339a7919f14610424576101cf565b8063095ea7b3116101ad578063095ea7b3146103385780630c340a241461037857806318160ddd1461039c57806323b872dd146103a4576101cf565b806306fdde03146101d4578063077f224a14610251578063077f22b71461031e575b600080fd5b6101dc610662565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61031c6004803603606081101561026757600080fd5b81019060208101813564010000000081111561028257600080fd5b82018360208201111561029457600080fd5b803590602001918460018302840111640100000000831117156102b657600080fd5b9193909290916020810190356401000000008111156102d457600080fd5b8201836020820111156102e657600080fd5b8035906020019184600183028401116401000000008311171561030857600080fd5b9193509150356001600160a01b03166106f9565b005b610326610896565b60408051918252519081900360200190f35b6103646004803603604081101561034e57600080fd5b506001600160a01b03813516906020013561089c565b604080519115158252519081900360200190f35b610380610903565b604080516001600160a01b039092168252519081900360200190f35b610326610912565b610364600480360360608110156103ba57600080fd5b506001600160a01b03813581169160208101359091169060400135610918565b6103e2610a73565b6040805160ff9092168252519081900360200190f35b6103646004803603604081101561040e57600080fd5b506001600160a01b038135169060200135610a7c565b61031c6004803603602081101561043a57600080fd5b5035610b15565b610326610d8f565b61031c6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610d95565b610380610dfc565b6104a36004803603602081101561049357600080fd5b50356001600160a01b0316610e0b565b604051808260028111156104b357fe5b60ff16815260200191505060405180910390f35b61031c610e20565b610326600480360360208110156104e557600080fd5b50356001600160a01b0316610e82565b610326610e94565b6103266004803603602081101561051357600080fd5b50356001600160a01b0316610e9a565b6101dc610ef8565b61031c6004803603604081101561054157600080fd5b506001600160a01b038135169060200135610f59565b6103646004803603604081101561056d57600080fd5b506001600160a01b038135169060200135610fbc565b6103646004803603604081101561059957600080fd5b506001600160a01b0381351690602001356110ab565b61031c6111a2565b6103646112cd565b61031c600480360360208110156105d557600080fd5b50356001600160a01b03166112f0565b610326600480360360408110156105fb57600080fd5b506001600160a01b038135811691602001351661139c565b6103266113c7565b61031c6113cd565b6106496004803603602081101561063957600080fd5b50356001600160a01b0316611534565b6040805192835260208301919091528051918290030190f35b60978054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b820191906000526020600020905b8154815290600101906020018083116106d157829003601f168201915b505050505090505b90565b6107016112cd565b610752576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b600054610100900460ff168061076b575061076b611561565b80610779575060005460ff16155b6107b45760405162461bcd60e51b815260040180806020018281038252602e8152602001806121eb602e913960400191505060405180910390fd5b600054610100900460ff161580156107df576000805460ff1961ff0019909116610100171660011790555b61085586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525060129250611567915050565b670de0b6b3a7640000609f55609c80546001600160a01b0319166001600160a01b038416179055801561088e576000805461ff00191690555b505050505050565b609e5481565b336000818152609b602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090d6115a7565b905090565b609a5490565b60006001600160a01b038316610970576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61097984610e9a565b8211156109cd576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b6001600160a01b0384166000908152609b60209081526040808320338452909152902054610a01908363ffffffff6115cc16565b6001600160a01b0385166000908152609b60209081526040808320338452909152902055610a30848484611615565b826001600160a01b0316846001600160a01b0316600080516020612219833981519152846040518082815260200191505060405180910390a35060019392505050565b60995460ff1690565b336000908152609b602090815260408083206001600160a01b0386168452909152812054610ab0908363ffffffff6117ad16565b336000818152609b602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b609c546001600160a01b03163314610b6e576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b6000805160206121aa83398151915280546002811415610bc6576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556000609a5411610c21576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420696e637265617365203020737570706c790000000000000000604482015290519081900360640190fd5b82609a541415610c7757609a54609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a1610d87565b6001600160801b038311610c8b5782610c94565b6001600160801b035b609a81905560a054610cbe91610caf9163ffffffff6115cc16565b609e549063ffffffff61180716565b609f819055610d14576040805162461bcd60e51b815260206004820152601860248201527f496e76616c6964206368616e676520696e20737570706c790000000000000000604482015290519081900360640190fd5b610d3d60a054610d31609f54609e5461180790919063ffffffff16565b9063ffffffff6117ad16565b609a819055609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a15b506001905550565b609a5481565b609c546001600160a01b03163314610dee576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df8828261183c565b5050565b609c546001600160a01b031681565b60a26020526000908152604090205460ff1681565b610e28611a25565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b81526004018080602001828103825260308152602001806122396030913960400191505060405180910390fd5b610e8033611a4a565b565b60a16020526000908152604090205481565b609f5481565b6001600160a01b0381166000908152609d6020526040812054610ebf57506000610ef3565b610ef0610ecb83611af8565b6001600160a01b0384166000908152609d60205260409020549063ffffffff61180716565b90505b919050565b60988054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b609c546001600160a01b03163314610fb2576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df88282611b3e565b336000908152609b602090815260408083206001600160a01b038616845290915281205480831061101057336000908152609b602090815260408083206001600160a01b0388168452909152812055611045565b611020818463ffffffff6115cc16565b336000908152609b602090815260408083206001600160a01b03891684529091529020555b336000818152609b602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60006001600160a01b038316611103576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61110c33610e9a565b821115611160576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b61116b338484611615565b6040805183815290516001600160a01b0385169133916000805160206122198339815191529181900360200190a350600192915050565b6000805160206121aa833981519152805460028114156111fa576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561120733611d88565b15611259576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e7420686173206e6f74206f7074656420696e0000000000000000604482015290519081900360640190fd5b61127461126533610e9a565b60a0549063ffffffff6117ad16565b60a055609f5433600090815260a16020908152604080832093909355609d90522054609e546112a89163ffffffff6115cc16565b609e555033600090815260a260205260409020805460ff191660019081179091559055565b60006112d76115a7565b6001600160a01b0316336001600160a01b031614905090565b6112f86112cd565b611349576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61135281611df4565b806001600160a01b03166113646115a7565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b6001600160a01b039182166000908152609b6020908152604080832093909416825291909152205490565b60a05481565b6000805160206121aa83398151915280546002811415611425576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561143233611d88565b611483576040805162461bcd60e51b815260206004820152601960248201527f4163636f756e7420686173206e6f74206f70746564206f757400000000000000604482015290519081900360640190fd5b60006114bf61149133611af8565b609f54336000908152609d60205260409020546114b39163ffffffff611e1816565b9063ffffffff611e7116565b90506114dc6114cd33610e9a565b60a0549063ffffffff6115cc16565b60a055336000908152609d60205260409020819055609e54611504908263ffffffff6117ad16565b609e55505033600090815260a260209081526040808320805460ff1916600217905560a190915281205560019055565b6001600160a01b0381166000908152609d6020526040812054819061155884611af8565b91509150915091565b303b1590565b825161157a906097906020860190612111565b50815161158e906098906020850190612111565b506099805460ff191660ff929092169190911790555050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600061160e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611eb3565b9392505050565b600061162083611d88565b9050600061162d85611d88565b9050600061164a61163d86611af8565b859063ffffffff611f4a16565b9050600061166761165a88611af8565b869063ffffffff611f4a16565b90506116d8816040518060400160405280601f81526020017f5472616e7366657220616d6f756e7420657863656564732062616c616e636500815250609d60008b6001600160a01b03166001600160a01b0316815260200190815260200160002054611eb39092919063ffffffff16565b6001600160a01b038089166000908152609d6020526040808220939093559088168152205461170d908363ffffffff6117ad16565b6001600160a01b0387166000908152609d6020526040902055838015611731575082155b156117675760a054611749908663ffffffff6117ad16565b60a055609e5461175f908263ffffffff6115cc16565b609e556117a4565b831580156117725750825b156117a45760a05461178a908663ffffffff6115cc16565b60a055609e546117a0908363ffffffff6117ad16565b609e555b50505050505050565b60008282018381101561160e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008061182284670de0b6b3a764000063ffffffff611e1816565b9050611834818463ffffffff611e7116565b949350505050565b6000805160206121aa83398151915280546002811415611894576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b0384166118f3576040805162461bcd60e51b815260206004820152601860248201527f4d696e7420746f20746865207a65726f20616464726573730000000000000000604482015290519081900360640190fd5b60006118fe85611d88565b9050600061190e61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915061193a908263ffffffff6117ad16565b6001600160a01b0387166000908152609d602052604090205581156119745760a05461196c908663ffffffff6117ad16565b60a05561198b565b609e54611987908263ffffffff6117ad16565b609e555b609a5461199e908663ffffffff6117ad16565b609a8190556001600160801b03116119ea576040805162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b604482015290519081900360640190fd5b6040805186815290516001600160a01b038816916000916000805160206122198339815191529181900360200190a350506001825550505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116611aa5576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316611ab76115a7565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3611af581611f5f565b50565b6001600160a01b038116600090815260a1602052604081205415611b3557506001600160a01b038116600090815260a16020526040902054610ef3565b50609f54610ef3565b6000805160206121aa83398151915280546002811415611b96576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b038416611bf5576040805162461bcd60e51b815260206004820152601a60248201527f4275726e2066726f6d20746865207a65726f2061646472657373000000000000604482015290519081900360640190fd5b82611bff57611d7f565b6000611c0a85611d88565b90506000611c1a61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915080821480611c4657508160018203145b15611c69576001600160a01b0387166000908152609d6020526040812055611cfe565b81811115611cb8576001600160a01b0387166000908152609d6020526040902054611c9a908363ffffffff6115cc16565b6001600160a01b0388166000908152609d6020526040902055611cfe565b6040805162461bcd60e51b815260206004820152601660248201527552656d6f766520657863656564732062616c616e636560501b604482015290519081900360640190fd5b8215611d1f5760a054611d17908763ffffffff6115cc16565b60a055611d36565b609e54611d32908363ffffffff6115cc16565b609e555b609a54611d49908763ffffffff6115cc16565b609a556040805187815290516000916001600160a01b038a16916000805160206122198339815191529181900360200190a35050505b50600190555050565b600080611d9483611f83565b9050808015611dc757506001600160a01b038316600090815260a2602052604081205460ff166002811115611dc557fe5b145b15611dd557611dd583611fbc565b50506001600160a01b0316600090815260a16020526040902054151590565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600082611e27575060006108fd565b82820282848281611e3457fe5b041461160e5760405162461bcd60e51b81526004018080602001828103825260218152602001806121ca6021913960400191505060405180910390fd5b600061160e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061207e565b60008184841115611f425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f07578181015183820152602001611eef565b50505050905090810190601f168015611f345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061160e8383670de0b6b3a76400006120e3565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611834575050151592915050565b6001600160a01b038116600090815260a16020526040902054611af5576001600160a01b0381166000908152609d6020526040902054612022576001600160a01b038116600090815260a1602052604090206b033b2e3c9fd0803ce80000009055611af5565b609f546001600160a01b038216600090815260a1602052604090205561204a61126582610e9a565b60a0556001600160a01b0381166000908152609d6020526040902054609e546120789163ffffffff6115cc16565b609e5550565b600081836120cd5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611f07578181015183820152602001611eef565b5060008385816120d957fe5b0495945050505050565b6000806120f6858563ffffffff611e1816565b9050612108818463ffffffff611e7116565b95945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061215257805160ff191683800117855561217f565b8280016001018555821561217f579182015b8281111561217f578251825591602001919060010190612164565b5061218b92915061218f565b5090565b6106f691905b8082111561218b576000815560010161219556fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820cd6d1104ba3da6a25fe62bc6f9a1a33a9dda54786ec6f85e49ec318bf70a0c5664736f6c634300050b0032", "devdoc": { "methods": { "allowance(address,address)": { diff --git a/contracts/deployments/mainnet/VaultCore.json b/contracts/deployments/mainnet/VaultCore.json index 1276cc0fd8..e5964fb2be 100644 --- a/contracts/deployments/mainnet/VaultCore.json +++ b/contracts/deployments/mainnet/VaultCore.json @@ -1,5 +1,5 @@ { - "address": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", + "address": "0xA4D15507112c0DB37E1320Bf3Fff8891DFd1D2Ed", "abi": [ { "constant": true, @@ -816,42 +816,42 @@ "type": "event" } ], - "transactionHash": "0x2bb4dcc3341a628b2de438b9b0e7294c470f8ca4d3b9ad2b5ec5786b6c652350", + "transactionHash": "0x07cabccc82a3ac9524ff28b42b01f37303c38ee5699bff83ea27cfebc9d35962", "receipt": { "to": null, "from": "0x71F78361537A6f7B6818e7A760c8bC0146D93f50", - "contractAddress": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", + "contractAddress": "0xA4D15507112c0DB37E1320Bf3Fff8891DFd1D2Ed", "transactionIndex": 9, - "gasUsed": "3137806", - "logsBloom": "0x00000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000800000000000001", - "blockHash": "0x820be6d39bd4deb192f62c2710c48fa0c6eb039283fa85a81592d4a74e50bf12", - "transactionHash": "0x2bb4dcc3341a628b2de438b9b0e7294c470f8ca4d3b9ad2b5ec5786b6c652350", + "gasUsed": "3105563", + "logsBloom": "0x00000000000000000000000000001000000000000000001000000000000000000000000000000000000000000000000100008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000200000000000000000020000000000000000000000000000000000000000000000000000000000000000200", + "blockHash": "0x450b3debcf95c77214a18901310bc0591b87ff8edddc2fcb976329177ca5fafc", + "transactionHash": "0x07cabccc82a3ac9524ff28b42b01f37303c38ee5699bff83ea27cfebc9d35962", "logs": [ { "transactionIndex": 9, - "blockNumber": 12104648, - "transactionHash": "0x2bb4dcc3341a628b2de438b9b0e7294c470f8ca4d3b9ad2b5ec5786b6c652350", - "address": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", + "blockNumber": 12750988, + "transactionHash": "0x07cabccc82a3ac9524ff28b42b01f37303c38ee5699bff83ea27cfebc9d35962", + "address": "0xA4D15507112c0DB37E1320Bf3Fff8891DFd1D2Ed", "topics": [ "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x00000000000000000000000071f78361537a6f7b6818e7a760c8bc0146d93f50" ], "data": "0x", - "logIndex": 27, - "blockHash": "0x820be6d39bd4deb192f62c2710c48fa0c6eb039283fa85a81592d4a74e50bf12" + "logIndex": 37, + "blockHash": "0x450b3debcf95c77214a18901310bc0591b87ff8edddc2fcb976329177ca5fafc" } ], - "blockNumber": 12104648, - "cumulativeGasUsed": "3979924", + "blockNumber": 12750988, + "cumulativeGasUsed": "4728031", "status": 1, "byzantium": true }, "args": [], - "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", + "solcInputHash": "c2ea476b4aec8b6a8c5cdeb6adf2172f", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592\"},\"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 if (_creditBalances[_account] == 0) {\\n // Since there is no existing balance, we can directly set to\\n // high resolution, and do not have to do any other bookkeeping\\n nonRebasingCreditsPerToken[_account] = 1e27;\\n } else {\\n // Migrate an existing account:\\n\\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(\\n _creditBalances[_account]\\n );\\n }\\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\":\"0x24b5da93d2279b02336983588dada1fecd3360b5df7074d83f2a79170f4216df\"},\"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 _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 // Calculate redemption outputs\\n (\\n uint256[] memory outputs,\\n uint256 _backingValue\\n ) = _calculateRedeemOutputs(_amount);\\n\\n // Check that OUSD is backed by enough assets\\n uint256 _totalSupply = oUSD.totalSupply();\\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 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 // 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 _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 (\\n uint256[] memory outputs,\\n uint256 totalValue\\n ) = _calculateRedeemOutputs(_amount);\\n return outputs;\\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, uint256 totalBalance)\\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 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\":\"0xb732b740a89c153297d79b32aa466722750da0ea5e698b4d952cd255ece6a6b3\"},\"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": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b6000805160206200372983398151915255565b600080516020620037298339815191525490565b61363780620000f26000396000f3fe6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610ad1565b3480156102ed57600080fd5b50610233610ad7565b34801561030257600080fd5b5061030b610add565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610b3f565b34801561037c57600080fd5b5061025a610b45565b34801561039157600080fd5b50610233610b54565b3480156103a657600080fd5b506103af610b5a565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610b6a565b3480156103e457600080fd5b506102ca610b79565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610bdb565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610bec565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610c03565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610d35565b3480156104b057600080fd5b50610233610df4565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610dfa565b3480156104f857600080fd5b50610233610e18565b34801561050d57600080fd5b50610233610e1e565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610e24565b34801561055557600080fd5b506102ca610e3f565b34801561056a57600080fd5b506102ca610efa565b34801561057f57600080fd5b5061025a610faf565b34801561059457600080fd5b506103af610fbe565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b0316610fe1565b3480156105dc57600080fd5b5061023361108d565b3480156105f157600080fd5b506103af611097565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b9193509150356110a7565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b03166115a2565b60385481565b600061070c611663565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f9833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603754604080516315d5220f60e31b81526001600160a01b0388811660048301529151600093929092169163aea9107891602480820192602092909190829003018186803b1580156108d857600080fd5b505afa1580156108ec573d6000803e3d6000fd5b505050506040513d602081101561090257600080fd5b505190506305f5e10081111561091957506305f5e1005b600061092487611688565b9050600061093c87601284900363ffffffff61174216565b9050600061096661095485600a63ffffffff61174216565b8990600a86900a63ffffffff61179c16565b905086156109c357868110156109c3576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a1a5750603754600160a01b900460ff16155b15610a2757610a276117ca565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b508b9250610ab09150506001600160a01b03821633308c63ffffffff611af116565b603a548310610ac157610ac1611b51565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b3557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b17575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610b816120dc565b6001600160a01b0316336001600160a01b031614610bd05760405162461bcd60e51b81526004018080602001828103825260308152602001806135d36030913960400191505060405180910390fd5b610bd933612101565b565b6000610be6826121af565b92915050565b6060806000610bfa84612370565b50949350505050565b603754600160a81b900460ff1615610c53576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610cab576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603c54604080516370a0823160e01b81523360048201529051610d2d926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610cfb57600080fd5b505afa158015610d0f573d6000803e3d6000fd5b505050506040513d6020811015610d2557600080fd5b505184612631565b506001905550565b603754600160a81b900460ff1615610d85576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610ddd576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610deb8484612631565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610e8f576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610ee7576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610ef3611b51565b5060019055565b603754600160a01b900460ff1615610f4b576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610fa3576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610ef36117ca565b6037546001600160a01b031681565b6000610fc8611663565b6001600160a01b0316336001600160a01b031614905090565b610fe9610fbe565b61103a576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61104381612be5565b806001600160a01b0316611055611663565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612c09565b603754600160a81b900460ff1681565b603754600160a81b900460ff16156110f7576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f98339815191528054600281141561114f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282558584146111a7576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b60008060606111b582612c2a565b905060005b898110156113ee57603360008c8c848181106111d257fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff16611242576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061125057fe5b90506020020135116112a9576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b6034548110156113e557603481815481106112c357fe5b6000918252602090912001546001600160a01b03168c8c848181106112e457fe5b905060200201356001600160a01b03166001600160a01b031614156113dd57600061132f6034838154811061131557fe5b6000918252602090912001546001600160a01b0316611688565b9050600084838151811061133f57fe5b60200260200101519050670de0b6b3a76400008111156113645750670de0b6b3a76400005b61139c61138f836012038e8e8881811061137a57fe5b9050602002013561174290919063ffffffff16565b889063ffffffff612d4016565b96506113d86113cb8284600a0a8f8f898181106113b557fe5b9050602002013561179c9092919063ffffffff16565b879063ffffffff612d4016565b955050505b6001016112ac565b506001016111ba565b50851561144a578582101561144a576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b5483101580156114a15750603754600160a01b900460ff16155b156114ae576114ae6117ca565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b15801561150157600080fd5b505af1158015611515573d6000803e3d6000fd5b506000925050505b898110156115805760008b8b8381811061153357fe5b905060200201356001600160a01b0316905061157733308c8c8681811061155657fe5b90506020020135846001600160a01b0316611af1909392919063ffffffff16565b5060010161151d565b50603a54831061159257611592611b51565b5050506001825550505050505050565b6115aa610fbe565b6115fb576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61160481612da1565b61163f5760405162461bcd60e51b81526004018080602001828103825260248152602001806135196024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156116c457600080fd5b505afa1580156116d8573d6000803e3d6000fd5b505050506040513d60208110156116ee57600080fd5b505160ff16905060048110801590611707575060128111155b610be65760405162461bcd60e51b815260040180806020018281038252602981526020018061353d6029913960400191505060405180910390fd5b6000808260000b131561176d5761176683600084900b600a0a63ffffffff612ddd16565b9250611795565b60008260000b121561179557611792836000848103900b600a0a63ffffffff612e3616565b92505b5090919050565b6000806117af858563ffffffff612ddd16565b90506117c1818463ffffffff612e3616565b95945050505050565b603754600160a01b900460ff161561181b576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561186057600080fd5b505afa158015611874573d6000803e3d6000fd5b505050506040513d602081101561188a57600080fd5b50519050806118995750610bd9565b60006118a3612c09565b6042549091506001600160a01b031680158015906118c057508282115b15611a025760006118d7838563ffffffff612e7816565b905060006119026127106118f660435485612ddd90919063ffffffff16565b9063ffffffff612e3616565b90508082116119425760405162461bcd60e51b81526004018080602001828103825260228152602001806135876022913960400191505060405180910390fd5b80156119b657603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b15801561199d57600080fd5b505af11580156119b1573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5057600080fd5b505afa158015611a64573d6000803e3d6000fd5b505050506040513d6020811015611a7a57600080fd5b5051925082821115611aec57603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611ad357600080fd5b505af1158015611ae7573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611b4b908590612eba565b50505050565b6000611b5b613072565b905080611b685750610bd9565b6000611b7261316f565b90506000611b86838363ffffffff612d4016565b9050600082611bb257603954611bab90670de0b6b3a76400009063ffffffff612e7816565b9050611bfe565b611bcb846118f684603954612ddd90919063ffffffff16565b905080670de0b6b3a76400001115611bf557611bab670de0b6b3a76400008263ffffffff612e7816565b50505050610bd9565b80611c0c5750505050610bd9565b60005b603454811015611d9b57600060348281548110611c2857fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611c7b57600080fd5b505afa158015611c8f573d6000803e3d6000fd5b505050506040513d6020811015611ca557600080fd5b5051905080611cb5575050611d93565b6000611cc7828663ffffffff6131c116565b6001600160a01b03808516600090815260406020819052902054919250168015801590611cf45750600082115b15611d8e5780611d146001600160a01b038616828563ffffffff6131d616565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611d7457600080fd5b505af1158015611d88573d6000803e3d6000fd5b50505050505b505050505b600101611c0f565b5060005b60365481101561206d57600060368281548110611db857fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b158015611e0557600080fd5b505afa158015611e19573d6000803e3d6000fd5b505050506040513d6020811015611e2f57600080fd5b505190506001600160a01b03811615612063576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b158015611e7d57600080fd5b505afa158015611e91573d6000803e3d6000fd5b505050506040513d6020811015611ea757600080fd5b5051905080611f3657306001600160a01b0316630e5c011e60368681548110611ecc57fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b158015611f1957600080fd5b505af1158015611f2d573d6000803e3d6000fd5b50505050612061565b60008290506000816001600160a01b03166370a0823160368881548110611f5957fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015611fa757600080fd5b505afa158015611fbb573d6000803e3d6000fd5b505050506040513d6020811015611fd157600080fd5b5051905082811061205e57306001600160a01b0316630e5c011e60368881548110611ff857fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561204557600080fd5b505af1158015612059573d6000803e3d6000fd5b505050505b50505b505b5050600101611d9f565b50604260009054906101000a90046001600160a01b03166001600160a01b0316638119c0656040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120be57600080fd5b505af11580156120d2573d6000803e3d6000fd5b5050505050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b03811661215c576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661216e611663565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36121ac81613228565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156121fa57600080fd5b505afa15801561220e573d6000803e3d6000fd5b505050506040513d602081101561222457600080fd5b5051915060005b6036548110156123695760006036828154811061224457fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561229a57600080fd5b505afa1580156122ae573d6000803e3d6000fd5b505050506040513d60208110156122c457600080fd5b5051156123605761235d816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561232457600080fd5b505afa158015612338573d6000803e3d6000fd5b505050506040513d602081101561234e57600080fd5b5051859063ffffffff612d4016565b93505b5060010161222b565b5050919050565b606060008061237d610e1e565b9050606061238b6001612c2a565b90506060826040519080825280602002602001820160405280156123b9578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156123e8578160200160208202803883390190505b50905060008090508460405190808252806020026020018201604052801561241a578160200160208202803883390190505b50603854909750156124595760006124436127106118f66038548c612ddd90919063ffffffff16565b9050612455898263ffffffff612e7816565b9850505b60005b6034548110156125095760006124926034838154811061247857fe5b6000918252602090912001546001600160a01b03166121af565b905060006124a66034848154811061131557fe5b9050818684815181106124b557fe5b602002602001018181525050808584815181106124ce57fe5b60209081029190910101526124fd6124f083601284900363ffffffff61174216565b8a9063ffffffff612d4016565b9850505060010161245c565b5060005b6034548110156125ba57600085828151811061252557fe5b60200260200101519050670de0b6b3a764000081101561254a5750670de0b6b3a76400005b600061259c896118f68461259089888151811061256357fe5b60200260200101516012038b898151811061257a57fe5b602002602001015161174290919063ffffffff16565b9063ffffffff612ddd16565b90506125ae848263ffffffff612d4016565b9350505060010161250d565b5060006125cd898363ffffffff61324c16565b905060005b60345481101561262557612606886118f6848885815181106125f057fe5b6020026020010151612ddd90919063ffffffff16565b89828151811061261257fe5b60209081029190910101526001016125d2565b50505050505050915091565b60008211612686576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b6060600061269384612370565b915091506000603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126e757600080fd5b505afa1580156126fb573d6000803e3d6000fd5b505050506040513d602081101561271157600080fd5b5051604154909150156127ce576000612730828463ffffffff61324c16565b9050604154670de0b6b3a764000082116127615761275c670de0b6b3a76400008363ffffffff612e7816565b612779565b61277982670de0b6b3a764000063ffffffff612e7816565b11156127cc576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810187905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160005b603454811015612a9d5783818151811061282257fe5b60200260200101516000141561283757612a95565b60006034828154811061284657fe5b60009182526020909120015485516001600160a01b03909116915085908390811061286d57fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156128cb57600080fd5b505afa1580156128df573d6000803e3d6000fd5b505050506040513d60208110156128f557600080fd5b5051106129325761292d3386848151811061290c57fe5b6020026020010151836001600160a01b03166131d69092919063ffffffff16565b612a93565b6000604060006034858154811061294557fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612a52576000819050806001600160a01b031663d9caed12336034878154811061299a57fe5b9060005260206000200160009054906101000a90046001600160a01b03168a88815181106129c457fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612a3457600080fd5b505af1158015612a48573d6000803e3d6000fd5b5050505050612a91565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b60010161280c565b508315612b4b576000805b8451811015612af3576000612ac36034838154811061131557fe5b9050612ae8612adb8260120388858151811061257a57fe5b849063ffffffff612d4016565b925050600101612aa8565b5084811015612b49576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612b9e57600080fd5b505af1158015612bb2573d6000803e3d6000fd5b50505050603b5485118015612bd15750603754600160a01b900460ff16155b15612bde57612bde6117ca565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612c1661316f565b612c1e613072565b9063ffffffff612d4016565b6060612c34610e1e565b604051908082528060200260200182016040528015612c5d578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561236957612d21600a836001600160a01b031663aea9107860348581548110612c9b57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015612ce957600080fd5b505afa158015612cfd573d6000803e3d6000fd5b505050506040513d6020811015612d1357600080fd5b50519063ffffffff61174216565b838281518110612d2d57fe5b6020908102919091010152600101612c70565b600082820183811015612d9a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612dd557508115155b949350505050565b600082612dec57506000610be6565b82820282848281612df957fe5b0414612d9a5760405162461bcd60e51b81526004018080602001828103825260218152602001806135666021913960400191505060405180910390fd5b6000612d9a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613279565b6000612d9a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061331b565b612ecc826001600160a01b0316612da1565b612f1d576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612f5b5780518252601f199092019160209182019101612f3c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612fbd576040519150601f19603f3d011682016040523d82523d6000602084013e612fc2565b606091505b509150915081613019576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611b4b5780806020019051602081101561303557600080fd5b5051611b4b5760405162461bcd60e51b815260040180806020018281038252602a8152602001806135a9602a913960400191505060405180910390fd5b6000805b60345481101561316b5760006034828154811061308f57fe5b6000918252602082200154603480546001600160a01b0390921693506130b9918590811061131557fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b15801561310557600080fd5b505afa158015613119573d6000803e3d6000fd5b505050506040513d602081101561312f57600080fd5b5051905080156131605761315d61315082601285900363ffffffff61174216565b869063ffffffff612d4016565b94505b505050600101613076565b5090565b6000805b60365481101561316b576131b76131aa6036838154811061319057fe5b6000918252602090912001546001600160a01b0316613375565b839063ffffffff612d4016565b9150600101613173565b6000612d9a8383670de0b6b3a764000061179c565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611aec908490612eba565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061326784670de0b6b3a764000063ffffffff612ddd16565b9050612dd5818463ffffffff612e3616565b600081836133055760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156132ca5781810151838201526020016132b2565b50505050905090810190601f1680156132f75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161331157fe5b0495945050505050565b6000818484111561336d5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156132ca5781810151838201526020016132b2565b505050900390565b600081815b6034548110156123695760006133966034838154811061131557fe5b9050826001600160a01b031663aa388af6603484815481106133b457fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561340257600080fd5b505afa158015613416573d6000803e3d6000fd5b505050506040513d602081101561342c57600080fd5b5051156134ef576000836001600160a01b0316635f5152266034858154811061345157fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561349f57600080fd5b505afa1580156134b3573d6000803e3d6000fd5b505050506040513d60208110156134c957600080fd5b5051905080156134ed576134ea61315082601285900363ffffffff61174216565b94505b505b5060010161337a56fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158203f7824d3dfb9099003a39f9d314f7e755aeb69e5e84049357c6b4bf3ae75ec8964736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610ad1565b3480156102ed57600080fd5b50610233610ad7565b34801561030257600080fd5b5061030b610add565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610b3f565b34801561037c57600080fd5b5061025a610b45565b34801561039157600080fd5b50610233610b54565b3480156103a657600080fd5b506103af610b5a565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610b6a565b3480156103e457600080fd5b506102ca610b79565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610bdb565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610bec565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610c03565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610d35565b3480156104b057600080fd5b50610233610df4565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610dfa565b3480156104f857600080fd5b50610233610e18565b34801561050d57600080fd5b50610233610e1e565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610e24565b34801561055557600080fd5b506102ca610e3f565b34801561056a57600080fd5b506102ca610efa565b34801561057f57600080fd5b5061025a610faf565b34801561059457600080fd5b506103af610fbe565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b0316610fe1565b3480156105dc57600080fd5b5061023361108d565b3480156105f157600080fd5b506103af611097565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b9193509150356110a7565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b03166115a2565b60385481565b600061070c611663565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f9833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603754604080516315d5220f60e31b81526001600160a01b0388811660048301529151600093929092169163aea9107891602480820192602092909190829003018186803b1580156108d857600080fd5b505afa1580156108ec573d6000803e3d6000fd5b505050506040513d602081101561090257600080fd5b505190506305f5e10081111561091957506305f5e1005b600061092487611688565b9050600061093c87601284900363ffffffff61174216565b9050600061096661095485600a63ffffffff61174216565b8990600a86900a63ffffffff61179c16565b905086156109c357868110156109c3576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a1a5750603754600160a01b900460ff16155b15610a2757610a276117ca565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b508b9250610ab09150506001600160a01b03821633308c63ffffffff611af116565b603a548310610ac157610ac1611b51565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b3557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b17575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610b816120dc565b6001600160a01b0316336001600160a01b031614610bd05760405162461bcd60e51b81526004018080602001828103825260308152602001806135d36030913960400191505060405180910390fd5b610bd933612101565b565b6000610be6826121af565b92915050565b6060806000610bfa84612370565b50949350505050565b603754600160a81b900460ff1615610c53576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610cab576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603c54604080516370a0823160e01b81523360048201529051610d2d926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610cfb57600080fd5b505afa158015610d0f573d6000803e3d6000fd5b505050506040513d6020811015610d2557600080fd5b505184612631565b506001905550565b603754600160a81b900460ff1615610d85576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610ddd576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610deb8484612631565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610e8f576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610ee7576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610ef3611b51565b5060019055565b603754600160a01b900460ff1615610f4b576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610fa3576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610ef36117ca565b6037546001600160a01b031681565b6000610fc8611663565b6001600160a01b0316336001600160a01b031614905090565b610fe9610fbe565b61103a576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61104381612be5565b806001600160a01b0316611055611663565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612c09565b603754600160a81b900460ff1681565b603754600160a81b900460ff16156110f7576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f98339815191528054600281141561114f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282558584146111a7576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b60008060606111b582612c2a565b905060005b898110156113ee57603360008c8c848181106111d257fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff16611242576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061125057fe5b90506020020135116112a9576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b6034548110156113e557603481815481106112c357fe5b6000918252602090912001546001600160a01b03168c8c848181106112e457fe5b905060200201356001600160a01b03166001600160a01b031614156113dd57600061132f6034838154811061131557fe5b6000918252602090912001546001600160a01b0316611688565b9050600084838151811061133f57fe5b60200260200101519050670de0b6b3a76400008111156113645750670de0b6b3a76400005b61139c61138f836012038e8e8881811061137a57fe5b9050602002013561174290919063ffffffff16565b889063ffffffff612d4016565b96506113d86113cb8284600a0a8f8f898181106113b557fe5b9050602002013561179c9092919063ffffffff16565b879063ffffffff612d4016565b955050505b6001016112ac565b506001016111ba565b50851561144a578582101561144a576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b5483101580156114a15750603754600160a01b900460ff16155b156114ae576114ae6117ca565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b15801561150157600080fd5b505af1158015611515573d6000803e3d6000fd5b506000925050505b898110156115805760008b8b8381811061153357fe5b905060200201356001600160a01b0316905061157733308c8c8681811061155657fe5b90506020020135846001600160a01b0316611af1909392919063ffffffff16565b5060010161151d565b50603a54831061159257611592611b51565b5050506001825550505050505050565b6115aa610fbe565b6115fb576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61160481612da1565b61163f5760405162461bcd60e51b81526004018080602001828103825260248152602001806135196024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156116c457600080fd5b505afa1580156116d8573d6000803e3d6000fd5b505050506040513d60208110156116ee57600080fd5b505160ff16905060048110801590611707575060128111155b610be65760405162461bcd60e51b815260040180806020018281038252602981526020018061353d6029913960400191505060405180910390fd5b6000808260000b131561176d5761176683600084900b600a0a63ffffffff612ddd16565b9250611795565b60008260000b121561179557611792836000848103900b600a0a63ffffffff612e3616565b92505b5090919050565b6000806117af858563ffffffff612ddd16565b90506117c1818463ffffffff612e3616565b95945050505050565b603754600160a01b900460ff161561181b576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561186057600080fd5b505afa158015611874573d6000803e3d6000fd5b505050506040513d602081101561188a57600080fd5b50519050806118995750610bd9565b60006118a3612c09565b6042549091506001600160a01b031680158015906118c057508282115b15611a025760006118d7838563ffffffff612e7816565b905060006119026127106118f660435485612ddd90919063ffffffff16565b9063ffffffff612e3616565b90508082116119425760405162461bcd60e51b81526004018080602001828103825260228152602001806135876022913960400191505060405180910390fd5b80156119b657603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b15801561199d57600080fd5b505af11580156119b1573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5057600080fd5b505afa158015611a64573d6000803e3d6000fd5b505050506040513d6020811015611a7a57600080fd5b5051925082821115611aec57603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611ad357600080fd5b505af1158015611ae7573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611b4b908590612eba565b50505050565b6000611b5b613072565b905080611b685750610bd9565b6000611b7261316f565b90506000611b86838363ffffffff612d4016565b9050600082611bb257603954611bab90670de0b6b3a76400009063ffffffff612e7816565b9050611bfe565b611bcb846118f684603954612ddd90919063ffffffff16565b905080670de0b6b3a76400001115611bf557611bab670de0b6b3a76400008263ffffffff612e7816565b50505050610bd9565b80611c0c5750505050610bd9565b60005b603454811015611d9b57600060348281548110611c2857fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611c7b57600080fd5b505afa158015611c8f573d6000803e3d6000fd5b505050506040513d6020811015611ca557600080fd5b5051905080611cb5575050611d93565b6000611cc7828663ffffffff6131c116565b6001600160a01b03808516600090815260406020819052902054919250168015801590611cf45750600082115b15611d8e5780611d146001600160a01b038616828563ffffffff6131d616565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611d7457600080fd5b505af1158015611d88573d6000803e3d6000fd5b50505050505b505050505b600101611c0f565b5060005b60365481101561206d57600060368281548110611db857fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b158015611e0557600080fd5b505afa158015611e19573d6000803e3d6000fd5b505050506040513d6020811015611e2f57600080fd5b505190506001600160a01b03811615612063576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b158015611e7d57600080fd5b505afa158015611e91573d6000803e3d6000fd5b505050506040513d6020811015611ea757600080fd5b5051905080611f3657306001600160a01b0316630e5c011e60368681548110611ecc57fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b158015611f1957600080fd5b505af1158015611f2d573d6000803e3d6000fd5b50505050612061565b60008290506000816001600160a01b03166370a0823160368881548110611f5957fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015611fa757600080fd5b505afa158015611fbb573d6000803e3d6000fd5b505050506040513d6020811015611fd157600080fd5b5051905082811061205e57306001600160a01b0316630e5c011e60368881548110611ff857fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561204557600080fd5b505af1158015612059573d6000803e3d6000fd5b505050505b50505b505b5050600101611d9f565b50604260009054906101000a90046001600160a01b03166001600160a01b0316638119c0656040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120be57600080fd5b505af11580156120d2573d6000803e3d6000fd5b5050505050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b03811661215c576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661216e611663565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36121ac81613228565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156121fa57600080fd5b505afa15801561220e573d6000803e3d6000fd5b505050506040513d602081101561222457600080fd5b5051915060005b6036548110156123695760006036828154811061224457fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561229a57600080fd5b505afa1580156122ae573d6000803e3d6000fd5b505050506040513d60208110156122c457600080fd5b5051156123605761235d816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561232457600080fd5b505afa158015612338573d6000803e3d6000fd5b505050506040513d602081101561234e57600080fd5b5051859063ffffffff612d4016565b93505b5060010161222b565b5050919050565b606060008061237d610e1e565b9050606061238b6001612c2a565b90506060826040519080825280602002602001820160405280156123b9578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156123e8578160200160208202803883390190505b50905060008090508460405190808252806020026020018201604052801561241a578160200160208202803883390190505b50603854909750156124595760006124436127106118f66038548c612ddd90919063ffffffff16565b9050612455898263ffffffff612e7816565b9850505b60005b6034548110156125095760006124926034838154811061247857fe5b6000918252602090912001546001600160a01b03166121af565b905060006124a66034848154811061131557fe5b9050818684815181106124b557fe5b602002602001018181525050808584815181106124ce57fe5b60209081029190910101526124fd6124f083601284900363ffffffff61174216565b8a9063ffffffff612d4016565b9850505060010161245c565b5060005b6034548110156125ba57600085828151811061252557fe5b60200260200101519050670de0b6b3a764000081101561254a5750670de0b6b3a76400005b600061259c896118f68461259089888151811061256357fe5b60200260200101516012038b898151811061257a57fe5b602002602001015161174290919063ffffffff16565b9063ffffffff612ddd16565b90506125ae848263ffffffff612d4016565b9350505060010161250d565b5060006125cd898363ffffffff61324c16565b905060005b60345481101561262557612606886118f6848885815181106125f057fe5b6020026020010151612ddd90919063ffffffff16565b89828151811061261257fe5b60209081029190910101526001016125d2565b50505050505050915091565b60008211612686576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b6060600061269384612370565b915091506000603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126e757600080fd5b505afa1580156126fb573d6000803e3d6000fd5b505050506040513d602081101561271157600080fd5b5051604154909150156127ce576000612730828463ffffffff61324c16565b9050604154670de0b6b3a764000082116127615761275c670de0b6b3a76400008363ffffffff612e7816565b612779565b61277982670de0b6b3a764000063ffffffff612e7816565b11156127cc576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810187905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160005b603454811015612a9d5783818151811061282257fe5b60200260200101516000141561283757612a95565b60006034828154811061284657fe5b60009182526020909120015485516001600160a01b03909116915085908390811061286d57fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156128cb57600080fd5b505afa1580156128df573d6000803e3d6000fd5b505050506040513d60208110156128f557600080fd5b5051106129325761292d3386848151811061290c57fe5b6020026020010151836001600160a01b03166131d69092919063ffffffff16565b612a93565b6000604060006034858154811061294557fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612a52576000819050806001600160a01b031663d9caed12336034878154811061299a57fe5b9060005260206000200160009054906101000a90046001600160a01b03168a88815181106129c457fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612a3457600080fd5b505af1158015612a48573d6000803e3d6000fd5b5050505050612a91565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b60010161280c565b508315612b4b576000805b8451811015612af3576000612ac36034838154811061131557fe5b9050612ae8612adb8260120388858151811061257a57fe5b849063ffffffff612d4016565b925050600101612aa8565b5084811015612b49576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612b9e57600080fd5b505af1158015612bb2573d6000803e3d6000fd5b50505050603b5485118015612bd15750603754600160a01b900460ff16155b15612bde57612bde6117ca565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612c1661316f565b612c1e613072565b9063ffffffff612d4016565b6060612c34610e1e565b604051908082528060200260200182016040528015612c5d578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561236957612d21600a836001600160a01b031663aea9107860348581548110612c9b57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015612ce957600080fd5b505afa158015612cfd573d6000803e3d6000fd5b505050506040513d6020811015612d1357600080fd5b50519063ffffffff61174216565b838281518110612d2d57fe5b6020908102919091010152600101612c70565b600082820183811015612d9a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612dd557508115155b949350505050565b600082612dec57506000610be6565b82820282848281612df957fe5b0414612d9a5760405162461bcd60e51b81526004018080602001828103825260218152602001806135666021913960400191505060405180910390fd5b6000612d9a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613279565b6000612d9a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061331b565b612ecc826001600160a01b0316612da1565b612f1d576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612f5b5780518252601f199092019160209182019101612f3c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612fbd576040519150601f19603f3d011682016040523d82523d6000602084013e612fc2565b606091505b509150915081613019576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611b4b5780806020019051602081101561303557600080fd5b5051611b4b5760405162461bcd60e51b815260040180806020018281038252602a8152602001806135a9602a913960400191505060405180910390fd5b6000805b60345481101561316b5760006034828154811061308f57fe5b6000918252602082200154603480546001600160a01b0390921693506130b9918590811061131557fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b15801561310557600080fd5b505afa158015613119573d6000803e3d6000fd5b505050506040513d602081101561312f57600080fd5b5051905080156131605761315d61315082601285900363ffffffff61174216565b869063ffffffff612d4016565b94505b505050600101613076565b5090565b6000805b60365481101561316b576131b76131aa6036838154811061319057fe5b6000918252602090912001546001600160a01b0316613375565b839063ffffffff612d4016565b9150600101613173565b6000612d9a8383670de0b6b3a764000061179c565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611aec908490612eba565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061326784670de0b6b3a764000063ffffffff612ddd16565b9050612dd5818463ffffffff612e3616565b600081836133055760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156132ca5781810151838201526020016132b2565b50505050905090810190601f1680156132f75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161331157fe5b0495945050505050565b6000818484111561336d5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156132ca5781810151838201526020016132b2565b505050900390565b600081815b6034548110156123695760006133966034838154811061131557fe5b9050826001600160a01b031663aa388af6603484815481106133b457fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561340257600080fd5b505afa158015613416573d6000803e3d6000fd5b505050506040513d602081101561342c57600080fd5b5051156134ef576000836001600160a01b0316635f5152266034858154811061345157fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561349f57600080fd5b505afa1580156134b3573d6000803e3d6000fd5b505050506040513d60208110156134c957600080fd5b5051905080156134ed576134ea61315082601285900363ffffffff61174216565b94505b505b5060010161337a56fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158203f7824d3dfb9099003a39f9d314f7e755aeb69e5e84049357c6b4bf3ae75ec8964736f6c634300050b0032", "devdoc": { "methods": { "allocate()": { diff --git a/contracts/deployments/mainnet/solcInputs/c2ea476b4aec8b6a8c5cdeb6adf2172f.json b/contracts/deployments/mainnet/solcInputs/c2ea476b4aec8b6a8c5cdeb6adf2172f.json new file mode 100644 index 0000000000..afd7cd7d23 --- /dev/null +++ b/contracts/deployments/mainnet/solcInputs/c2ea476b4aec8b6a8c5cdeb6adf2172f.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 poolCoinIndex = _getPoolCoinIndex(_asset);\n uint256 curveBalance = curvePool.balances(poolCoinIndex);\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 balances(uint256) external view returns (uint256);\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 if (_creditBalances[_account] == 0) {\n // Since there is no existing balance, we can directly set to\n // high resolution, and do not have to do any other bookkeeping\n nonRebasingCreditsPerToken[_account] = 1e27;\n } else {\n // Migrate an existing account:\n\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(\n _creditBalances[_account]\n );\n }\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 _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 // Calculate redemption outputs\n (\n uint256[] memory outputs,\n uint256 _backingValue\n ) = _calculateRedeemOutputs(_amount);\n\n // Check that OUSD is backed by enough assets\n uint256 _totalSupply = oUSD.totalSupply();\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 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 // 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 _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 (\n uint256[] memory outputs,\n uint256 totalValue\n ) = _calculateRedeemOutputs(_amount);\n return outputs;\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, uint256 totalBalance)\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 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 uint256[3] public balances;\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 balances[uint256(i)] = balances[i].add(uint256(_amounts[i]));\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 balances[uint256(_index)] = balances[uint256(_index)].sub(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 balances[uint256(i)] = balances[uint256(i)].sub(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\";\nimport \"../utils/Helpers.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 _checkBalance(address _asset)\n internal\n view\n returns (uint256 balance)\n {\n // Avoids rounding errors by returning the total value\n // in a single currency\n if (allAssets[0] == _asset) {\n uint256 decimals = Helpers.getDecimals(_asset);\n return storedTotalValue.scaleBy(int8(decimals - 18));\n } else {\n return 0;\n }\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 b1e7d9ff2e..f16ea3f9cd 100644 --- a/contracts/deployments/rinkeby/.migrations.json +++ b/contracts/deployments/rinkeby/.migrations.json @@ -16,5 +16,6 @@ "015_flipper": 1613166556, "016_chainlink_and_buyback": 1616624684, "017_3pool_strategy_update": 1621302942, - "018_upgrade_governor": 1624425066 + "018_upgrade_governor": 1624425066, + "019_resolution_and_savings": 1625264902 } \ No newline at end of file diff --git a/contracts/deployments/rinkeby/OUSD.json b/contracts/deployments/rinkeby/OUSD.json index ad5fa76435..edb33abd2c 100644 --- a/contracts/deployments/rinkeby/OUSD.json +++ b/contracts/deployments/rinkeby/OUSD.json @@ -1,5 +1,5 @@ { - "address": "0x1e4277abF53A0BD4dACC22Fc0Ab2FF9eb2192786", + "address": "0x06bFb84169EFd5aFafa39cBbf5018EE8624ef29b", "abi": [ { "constant": true, @@ -652,42 +652,42 @@ "type": "event" } ], - "transactionHash": "0xf7d5cb4768772f4a09e6698c0bd27a1ab23508c1e2e4522146c4468f52077897", + "transactionHash": "0xf6489f408680ad08f312dd47effbe856dea82bec7f5b9b12061478282cd54ba1", "receipt": { "to": null, "from": "0xD85A569F3C26f81070544451131c742283360400", - "contractAddress": "0x1e4277abF53A0BD4dACC22Fc0Ab2FF9eb2192786", + "contractAddress": "0x06bFb84169EFd5aFafa39cBbf5018EE8624ef29b", "transactionIndex": 3, - "gasUsed": "1977489", - "logsBloom": "0x0000000040000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000800000000000010000000000000000000000000000000000000000020000000000000000000000000000000000000000400000000000000000000000000", - "blockHash": "0x323a07b67180531d16dfe9c14870c61fef0081cfdbe9f9bf3d6c92dc64791fae", - "transactionHash": "0xf7d5cb4768772f4a09e6698c0bd27a1ab23508c1e2e4522146c4468f52077897", + "gasUsed": "1995223", + "logsBloom": "0x00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000020000000000000000000800000000000000000000000000000000000004000000000000000000008000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000001000000000000000000000000010000000000000000000000000000000000000000020000000000000000000000000000000000000000400000000000000000000000000", + "blockHash": "0x9a833cf30d831479fb7b362c127150b49988d288d8f0b94e2df8eb08ac693a4d", + "transactionHash": "0xf6489f408680ad08f312dd47effbe856dea82bec7f5b9b12061478282cd54ba1", "logs": [ { "transactionIndex": 3, - "blockNumber": 8004237, - "transactionHash": "0xf7d5cb4768772f4a09e6698c0bd27a1ab23508c1e2e4522146c4468f52077897", - "address": "0x1e4277abF53A0BD4dACC22Fc0Ab2FF9eb2192786", + "blockNumber": 8868508, + "transactionHash": "0xf6489f408680ad08f312dd47effbe856dea82bec7f5b9b12061478282cd54ba1", + "address": "0x06bFb84169EFd5aFafa39cBbf5018EE8624ef29b", "topics": [ "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000d85a569f3c26f81070544451131c742283360400" ], "data": "0x", - "logIndex": 5, - "blockHash": "0x323a07b67180531d16dfe9c14870c61fef0081cfdbe9f9bf3d6c92dc64791fae" + "logIndex": 4, + "blockHash": "0x9a833cf30d831479fb7b362c127150b49988d288d8f0b94e2df8eb08ac693a4d" } ], - "blockNumber": 8004237, - "cumulativeGasUsed": "4189857", + "blockNumber": 8868508, + "cumulativeGasUsed": "2224983", "status": 1, "byzantium": true }, "args": [], - "solcInputHash": "c3af786fe12b6b771320281cb59e3482", - "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592.mod\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"string\",\"name\":\"_nameArg\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbolArg\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_vaultAddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasingCredits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newTotalSupply\",\"type\":\"uint256\"}],\"name\":\"changeSupply\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rebaseState\",\"outputs\":[{\"internalType\":\"enum OUSD.RebaseOptions\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonRebasingCreditsPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasingCreditsPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebaseOptOut\",\"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\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nonRebasingSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebaseOptIn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"creditsBalanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rebasingCredits\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rebasingCreditsPerToken\",\"type\":\"uint256\"}],\"name\":\"TotalSupplyUpdated\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allowance(address,address)\":{\"details\":\"Function to check the _amount of tokens that an owner has allowed to a _spender.\",\"params\":{\"_owner\":\"The address which owns the funds.\",\"_spender\":\"The address which will spend the funds.\"},\"return\":\"The number of tokens still available for the _spender.\"},\"approve(address,uint256)\":{\"details\":\"Approve the passed address to spend the specified _amount of tokens on behalf of msg.sender. This method is included for ERC20 compatibility. increaseAllowance and decreaseAllowance should be used instead. Changing an allowance with this method brings the risk that someone may transfer both the old and the new allowance - if they are both greater than zero - if a transfer transaction is mined before the later approve() call is mined.\",\"params\":{\"_spender\":\"The address which will spend the funds.\",\"_value\":\"The _amount of tokens to be spent.\"}},\"balanceOf(address)\":{\"details\":\"Gets the balance of the specified address.\",\"params\":{\"_account\":\"Address to query the balance of.\"},\"return\":\"A uint256 representing the _amount of base units owned by the specified address.\"},\"burn(address,uint256)\":{\"details\":\"Burns tokens, decreasing totalSupply.\"},\"changeSupply(uint256)\":{\"details\":\"Modify the supply without minting new tokens. This uses a change in the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\",\"params\":{\"_newTotalSupply\":\"New total supply of OUSD.\"},\"return\":\"uint256 representing the new total supply.\"},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"creditsBalanceOf(address)\":{\"details\":\"Gets the credits balance of the specified address.\",\"params\":{\"_account\":\"The address to query the balance of.\"},\"return\":\"(uint256, uint256) Credit balance and credits per token of the address\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). * Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. * NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Decrease the _amount of tokens that an owner has allowed to a _spender.\",\"params\":{\"_spender\":\"The address which will spend the funds.\",\"_subtractedValue\":\"The _amount of tokens to decrease the allowance by.\"}},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Increase the _amount of tokens that an owner has allowed to a _spender. This method should be used instead of approve() to avoid the double approval vulnerability described above.\",\"params\":{\"_addedValue\":\"The _amount of tokens to increase the allowance by.\",\"_spender\":\"The address which will spend the funds.\"}},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"mint(address,uint256)\":{\"details\":\"Mints new tokens, increasing totalSupply.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"rebaseOptIn()\":{\"details\":\"Add a contract address to the non rebasing exception list. I.e. the address's balance will be part of rebases so the account will be exposed to upside and downside.\"},\"rebaseOptOut()\":{\"details\":\"Remove a contract address to the non rebasing exception list.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"return\":\"The total supply of OUSD.\"},\"transfer(address,uint256)\":{\"details\":\"Transfer tokens to a specified address.\",\"params\":{\"_to\":\"the address to transfer to.\",\"_value\":\"the _amount to be transferred.\"},\"return\":\"true on success.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"Transfer tokens from one address to another.\",\"params\":{\"_from\":\"The address you want to send tokens from.\",\"_to\":\"The address you want to transfer to.\",\"_value\":\"The _amount of tokens to be transferred.\"}},\"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\":{},\"notice\":\"NOTE that this is an ERC20 token but the invariant that the sum of balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the rebasing design. Any integrations with OUSD should be aware.\"}},\"settings\":{\"compilationTarget\":{\"contracts/token/OUSD.sol\":\"OUSD\"},\"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/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/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/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\"}},\"version\":1}", - "bytecode": "0x6080604052609c80546001600160a01b031916905562000028336001600160e01b036200008116565b6200003b6001600160e01b036200009416565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000a8565b6000805160206200230c83398151915255565b6000805160206200230c8339815191525490565b61225480620000b86000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80635d36b19011610104578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105e5578063e696393a14610613578063f51b0fd41461061b578063f9854bfc14610623576101cf565b8063a9059cbb14610583578063c2376dff146105af578063c7af3352146105b7578063d38bfff4146105bf576101cf565b806370a08231116100de57806370a08231146104fd57806395d89b41146105235780639dc29fac1461052b578063a457c2d714610557576101cf565b80635d36b190146104c7578063609350cd146104cf5780636691cb3d146104f5576101cf565b8063313ce567116101715780633eaaf86b1161014b5780633eaaf86b1461044157806340c10f1914610449578063430bf08a14610475578063456ee2861461047d576101cf565b8063313ce567146103da57806339509351146103f857806339a7919f14610424576101cf565b8063095ea7b3116101ad578063095ea7b3146103385780630c340a241461037857806318160ddd1461039c57806323b872dd146103a4576101cf565b806306fdde03146101d4578063077f224a14610251578063077f22b71461031e575b600080fd5b6101dc610662565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61031c6004803603606081101561026757600080fd5b81019060208101813564010000000081111561028257600080fd5b82018360208201111561029457600080fd5b803590602001918460018302840111640100000000831117156102b657600080fd5b9193909290916020810190356401000000008111156102d457600080fd5b8201836020820111156102e657600080fd5b8035906020019184600183028401116401000000008311171561030857600080fd5b9193509150356001600160a01b03166106f9565b005b610326610896565b60408051918252519081900360200190f35b6103646004803603604081101561034e57600080fd5b506001600160a01b03813516906020013561089c565b604080519115158252519081900360200190f35b610380610903565b604080516001600160a01b039092168252519081900360200190f35b610326610912565b610364600480360360608110156103ba57600080fd5b506001600160a01b03813581169160208101359091169060400135610918565b6103e2610a73565b6040805160ff9092168252519081900360200190f35b6103646004803603604081101561040e57600080fd5b506001600160a01b038135169060200135610a7c565b61031c6004803603602081101561043a57600080fd5b5035610b15565b610326610d8f565b61031c6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610d95565b610380610dfc565b6104a36004803603602081101561049357600080fd5b50356001600160a01b0316610e0b565b604051808260028111156104b357fe5b60ff16815260200191505060405180910390f35b61031c610e20565b610326600480360360208110156104e557600080fd5b50356001600160a01b0316610e82565b610326610e94565b6103266004803603602081101561051357600080fd5b50356001600160a01b0316610e9a565b6101dc610ef8565b61031c6004803603604081101561054157600080fd5b506001600160a01b038135169060200135610f59565b6103646004803603604081101561056d57600080fd5b506001600160a01b038135169060200135610fbc565b6103646004803603604081101561059957600080fd5b506001600160a01b0381351690602001356110ab565b61031c6111a2565b6103646112cd565b61031c600480360360208110156105d557600080fd5b50356001600160a01b03166112f0565b610326600480360360408110156105fb57600080fd5b506001600160a01b038135811691602001351661139c565b6103266113c7565b61031c6113cd565b6106496004803603602081101561063957600080fd5b50356001600160a01b0316611534565b6040805192835260208301919091528051918290030190f35b60978054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b820191906000526020600020905b8154815290600101906020018083116106d157829003601f168201915b505050505090505b90565b6107016112cd565b610752576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b600054610100900460ff168061076b575061076b611561565b80610779575060005460ff16155b6107b45760405162461bcd60e51b815260040180806020018281038252602e8152602001806121a2602e913960400191505060405180910390fd5b600054610100900460ff161580156107df576000805460ff1961ff0019909116610100171660011790555b61085586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525060129250611567915050565b670de0b6b3a7640000609f55609c80546001600160a01b0319166001600160a01b038416179055801561088e576000805461ff00191690555b505050505050565b609e5481565b336000818152609b602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090d6115a7565b905090565b609a5490565b60006001600160a01b038316610970576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61097984610e9a565b8211156109cd576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b6001600160a01b0384166000908152609b60209081526040808320338452909152902054610a01908363ffffffff6115cc16565b6001600160a01b0385166000908152609b60209081526040808320338452909152902055610a30848484611615565b826001600160a01b0316846001600160a01b03166000805160206121d0833981519152846040518082815260200191505060405180910390a35060019392505050565b60995460ff1690565b336000908152609b602090815260408083206001600160a01b0386168452909152812054610ab0908363ffffffff6117ad16565b336000818152609b602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b609c546001600160a01b03163314610b6e576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b60008051602061216183398151915280546002811415610bc6576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556000609a5411610c21576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420696e637265617365203020737570706c790000000000000000604482015290519081900360640190fd5b82609a541415610c7757609a54609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a1610d87565b6001600160801b038311610c8b5782610c94565b6001600160801b035b609a81905560a054610cbe91610caf9163ffffffff6115cc16565b609e549063ffffffff61180716565b609f819055610d14576040805162461bcd60e51b815260206004820152601860248201527f496e76616c6964206368616e676520696e20737570706c790000000000000000604482015290519081900360640190fd5b610d3d60a054610d31609f54609e5461180790919063ffffffff16565b9063ffffffff6117ad16565b609a819055609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a15b506001905550565b609a5481565b609c546001600160a01b03163314610dee576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df8828261183c565b5050565b609c546001600160a01b031681565b60a26020526000908152604090205460ff1681565b610e28611a25565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b81526004018080602001828103825260308152602001806121f06030913960400191505060405180910390fd5b610e8033611a4a565b565b60a16020526000908152604090205481565b609f5481565b6001600160a01b0381166000908152609d6020526040812054610ebf57506000610ef3565b610ef0610ecb83611af8565b6001600160a01b0384166000908152609d60205260409020549063ffffffff61180716565b90505b919050565b60988054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b609c546001600160a01b03163314610fb2576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df88282611b3e565b336000908152609b602090815260408083206001600160a01b038616845290915281205480831061101057336000908152609b602090815260408083206001600160a01b0388168452909152812055611045565b611020818463ffffffff6115cc16565b336000908152609b602090815260408083206001600160a01b03891684529091529020555b336000818152609b602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60006001600160a01b038316611103576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61110c33610e9a565b821115611160576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b61116b338484611615565b6040805183815290516001600160a01b0385169133916000805160206121d08339815191529181900360200190a350600192915050565b600080516020612161833981519152805460028114156111fa576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561120733611d88565b15611259576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e7420686173206e6f74206f7074656420696e0000000000000000604482015290519081900360640190fd5b61127461126533610e9a565b60a0549063ffffffff6117ad16565b60a055609f5433600090815260a16020908152604080832093909355609d90522054609e546112a89163ffffffff6115cc16565b609e555033600090815260a260205260409020805460ff191660019081179091559055565b60006112d76115a7565b6001600160a01b0316336001600160a01b031614905090565b6112f86112cd565b611349576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61135281611df4565b806001600160a01b03166113646115a7565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b6001600160a01b039182166000908152609b6020908152604080832093909416825291909152205490565b60a05481565b60008051602061216183398151915280546002811415611425576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561143233611d88565b611483576040805162461bcd60e51b815260206004820152601960248201527f4163636f756e7420686173206e6f74206f70746564206f757400000000000000604482015290519081900360640190fd5b60006114bf61149133611af8565b609f54336000908152609d60205260409020546114b39163ffffffff611e1816565b9063ffffffff611e7116565b90506114dc6114cd33610e9a565b60a0549063ffffffff6115cc16565b60a055336000908152609d60205260409020819055609e54611504908263ffffffff6117ad16565b609e55505033600090815260a260209081526040808320805460ff1916600217905560a190915281205560019055565b6001600160a01b0381166000908152609d6020526040812054819061155884611af8565b91509150915091565b303b1590565b825161157a9060979060208601906120c8565b50815161158e9060989060208501906120c8565b506099805460ff191660ff929092169190911790555050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600061160e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611eb3565b9392505050565b600061162083611d88565b9050600061162d85611d88565b9050600061164a61163d86611af8565b859063ffffffff611f4a16565b9050600061166761165a88611af8565b869063ffffffff611f4a16565b90506116d8816040518060400160405280601f81526020017f5472616e7366657220616d6f756e7420657863656564732062616c616e636500815250609d60008b6001600160a01b03166001600160a01b0316815260200190815260200160002054611eb39092919063ffffffff16565b6001600160a01b038089166000908152609d6020526040808220939093559088168152205461170d908363ffffffff6117ad16565b6001600160a01b0387166000908152609d6020526040902055838015611731575082155b156117675760a054611749908663ffffffff6117ad16565b60a055609e5461175f908263ffffffff6115cc16565b609e556117a4565b831580156117725750825b156117a45760a05461178a908663ffffffff6115cc16565b60a055609e546117a0908363ffffffff6117ad16565b609e555b50505050505050565b60008282018381101561160e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008061182284670de0b6b3a764000063ffffffff611e1816565b9050611834818463ffffffff611e7116565b949350505050565b60008051602061216183398151915280546002811415611894576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b0384166118f3576040805162461bcd60e51b815260206004820152601860248201527f4d696e7420746f20746865207a65726f20616464726573730000000000000000604482015290519081900360640190fd5b60006118fe85611d88565b9050600061190e61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915061193a908263ffffffff6117ad16565b6001600160a01b0387166000908152609d602052604090205581156119745760a05461196c908663ffffffff6117ad16565b60a05561198b565b609e54611987908263ffffffff6117ad16565b609e555b609a5461199e908663ffffffff6117ad16565b609a8190556001600160801b03116119ea576040805162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b604482015290519081900360640190fd5b6040805186815290516001600160a01b038816916000916000805160206121d08339815191529181900360200190a350506001825550505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116611aa5576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316611ab76115a7565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3611af581611f5f565b50565b6001600160a01b038116600090815260a1602052604081205415611b3557506001600160a01b038116600090815260a16020526040902054610ef3565b50609f54610ef3565b60008051602061216183398151915280546002811415611b96576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b038416611bf5576040805162461bcd60e51b815260206004820152601a60248201527f4275726e2066726f6d20746865207a65726f2061646472657373000000000000604482015290519081900360640190fd5b82611bff57611d7f565b6000611c0a85611d88565b90506000611c1a61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915080821480611c4657508160018203145b15611c69576001600160a01b0387166000908152609d6020526040812055611cfe565b81811115611cb8576001600160a01b0387166000908152609d6020526040902054611c9a908363ffffffff6115cc16565b6001600160a01b0388166000908152609d6020526040902055611cfe565b6040805162461bcd60e51b815260206004820152601660248201527552656d6f766520657863656564732062616c616e636560501b604482015290519081900360640190fd5b8215611d1f5760a054611d17908763ffffffff6115cc16565b60a055611d36565b609e54611d32908363ffffffff6115cc16565b609e555b609a54611d49908763ffffffff6115cc16565b609a556040805187815290516000916001600160a01b038a16916000805160206121d08339815191529181900360200190a35050505b50600190555050565b600080611d9483611f83565b9050808015611dc757506001600160a01b038316600090815260a2602052604081205460ff166002811115611dc557fe5b145b15611dd557611dd583611fbc565b50506001600160a01b0316600090815260a16020526040902054151590565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600082611e27575060006108fd565b82820282848281611e3457fe5b041461160e5760405162461bcd60e51b81526004018080602001828103825260218152602001806121816021913960400191505060405180910390fd5b600061160e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612035565b60008184841115611f425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f07578181015183820152602001611eef565b50505050905090810190601f168015611f345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061160e8383670de0b6b3a764000061209a565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611834575050151592915050565b6001600160a01b038116600090815260a16020526040902054611af557609f546001600160a01b038216600090815260a1602052604090205561200161126582610e9a565b60a0556001600160a01b0381166000908152609d6020526040902054609e5461202f9163ffffffff6115cc16565b609e5550565b600081836120845760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611f07578181015183820152602001611eef565b50600083858161209057fe5b0495945050505050565b6000806120ad858563ffffffff611e1816565b90506120bf818463ffffffff611e7116565b95945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061210957805160ff1916838001178555612136565b82800160010185558215612136579182015b8281111561213657825182559160200191906001019061211b565b50612142929150612146565b5090565b6106f691905b80821115612142576000815560010161214c56fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158205227783b0c43cba340cfbfe748686c3a494c001c4b18954f2047eaf486aec56b64736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80635d36b19011610104578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105e5578063e696393a14610613578063f51b0fd41461061b578063f9854bfc14610623576101cf565b8063a9059cbb14610583578063c2376dff146105af578063c7af3352146105b7578063d38bfff4146105bf576101cf565b806370a08231116100de57806370a08231146104fd57806395d89b41146105235780639dc29fac1461052b578063a457c2d714610557576101cf565b80635d36b190146104c7578063609350cd146104cf5780636691cb3d146104f5576101cf565b8063313ce567116101715780633eaaf86b1161014b5780633eaaf86b1461044157806340c10f1914610449578063430bf08a14610475578063456ee2861461047d576101cf565b8063313ce567146103da57806339509351146103f857806339a7919f14610424576101cf565b8063095ea7b3116101ad578063095ea7b3146103385780630c340a241461037857806318160ddd1461039c57806323b872dd146103a4576101cf565b806306fdde03146101d4578063077f224a14610251578063077f22b71461031e575b600080fd5b6101dc610662565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61031c6004803603606081101561026757600080fd5b81019060208101813564010000000081111561028257600080fd5b82018360208201111561029457600080fd5b803590602001918460018302840111640100000000831117156102b657600080fd5b9193909290916020810190356401000000008111156102d457600080fd5b8201836020820111156102e657600080fd5b8035906020019184600183028401116401000000008311171561030857600080fd5b9193509150356001600160a01b03166106f9565b005b610326610896565b60408051918252519081900360200190f35b6103646004803603604081101561034e57600080fd5b506001600160a01b03813516906020013561089c565b604080519115158252519081900360200190f35b610380610903565b604080516001600160a01b039092168252519081900360200190f35b610326610912565b610364600480360360608110156103ba57600080fd5b506001600160a01b03813581169160208101359091169060400135610918565b6103e2610a73565b6040805160ff9092168252519081900360200190f35b6103646004803603604081101561040e57600080fd5b506001600160a01b038135169060200135610a7c565b61031c6004803603602081101561043a57600080fd5b5035610b15565b610326610d8f565b61031c6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610d95565b610380610dfc565b6104a36004803603602081101561049357600080fd5b50356001600160a01b0316610e0b565b604051808260028111156104b357fe5b60ff16815260200191505060405180910390f35b61031c610e20565b610326600480360360208110156104e557600080fd5b50356001600160a01b0316610e82565b610326610e94565b6103266004803603602081101561051357600080fd5b50356001600160a01b0316610e9a565b6101dc610ef8565b61031c6004803603604081101561054157600080fd5b506001600160a01b038135169060200135610f59565b6103646004803603604081101561056d57600080fd5b506001600160a01b038135169060200135610fbc565b6103646004803603604081101561059957600080fd5b506001600160a01b0381351690602001356110ab565b61031c6111a2565b6103646112cd565b61031c600480360360208110156105d557600080fd5b50356001600160a01b03166112f0565b610326600480360360408110156105fb57600080fd5b506001600160a01b038135811691602001351661139c565b6103266113c7565b61031c6113cd565b6106496004803603602081101561063957600080fd5b50356001600160a01b0316611534565b6040805192835260208301919091528051918290030190f35b60978054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b820191906000526020600020905b8154815290600101906020018083116106d157829003601f168201915b505050505090505b90565b6107016112cd565b610752576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b600054610100900460ff168061076b575061076b611561565b80610779575060005460ff16155b6107b45760405162461bcd60e51b815260040180806020018281038252602e8152602001806121a2602e913960400191505060405180910390fd5b600054610100900460ff161580156107df576000805460ff1961ff0019909116610100171660011790555b61085586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525060129250611567915050565b670de0b6b3a7640000609f55609c80546001600160a01b0319166001600160a01b038416179055801561088e576000805461ff00191690555b505050505050565b609e5481565b336000818152609b602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090d6115a7565b905090565b609a5490565b60006001600160a01b038316610970576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61097984610e9a565b8211156109cd576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b6001600160a01b0384166000908152609b60209081526040808320338452909152902054610a01908363ffffffff6115cc16565b6001600160a01b0385166000908152609b60209081526040808320338452909152902055610a30848484611615565b826001600160a01b0316846001600160a01b03166000805160206121d0833981519152846040518082815260200191505060405180910390a35060019392505050565b60995460ff1690565b336000908152609b602090815260408083206001600160a01b0386168452909152812054610ab0908363ffffffff6117ad16565b336000818152609b602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b609c546001600160a01b03163314610b6e576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b60008051602061216183398151915280546002811415610bc6576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556000609a5411610c21576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420696e637265617365203020737570706c790000000000000000604482015290519081900360640190fd5b82609a541415610c7757609a54609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a1610d87565b6001600160801b038311610c8b5782610c94565b6001600160801b035b609a81905560a054610cbe91610caf9163ffffffff6115cc16565b609e549063ffffffff61180716565b609f819055610d14576040805162461bcd60e51b815260206004820152601860248201527f496e76616c6964206368616e676520696e20737570706c790000000000000000604482015290519081900360640190fd5b610d3d60a054610d31609f54609e5461180790919063ffffffff16565b9063ffffffff6117ad16565b609a819055609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a15b506001905550565b609a5481565b609c546001600160a01b03163314610dee576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df8828261183c565b5050565b609c546001600160a01b031681565b60a26020526000908152604090205460ff1681565b610e28611a25565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b81526004018080602001828103825260308152602001806121f06030913960400191505060405180910390fd5b610e8033611a4a565b565b60a16020526000908152604090205481565b609f5481565b6001600160a01b0381166000908152609d6020526040812054610ebf57506000610ef3565b610ef0610ecb83611af8565b6001600160a01b0384166000908152609d60205260409020549063ffffffff61180716565b90505b919050565b60988054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b609c546001600160a01b03163314610fb2576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df88282611b3e565b336000908152609b602090815260408083206001600160a01b038616845290915281205480831061101057336000908152609b602090815260408083206001600160a01b0388168452909152812055611045565b611020818463ffffffff6115cc16565b336000908152609b602090815260408083206001600160a01b03891684529091529020555b336000818152609b602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60006001600160a01b038316611103576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61110c33610e9a565b821115611160576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b61116b338484611615565b6040805183815290516001600160a01b0385169133916000805160206121d08339815191529181900360200190a350600192915050565b600080516020612161833981519152805460028114156111fa576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561120733611d88565b15611259576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e7420686173206e6f74206f7074656420696e0000000000000000604482015290519081900360640190fd5b61127461126533610e9a565b60a0549063ffffffff6117ad16565b60a055609f5433600090815260a16020908152604080832093909355609d90522054609e546112a89163ffffffff6115cc16565b609e555033600090815260a260205260409020805460ff191660019081179091559055565b60006112d76115a7565b6001600160a01b0316336001600160a01b031614905090565b6112f86112cd565b611349576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61135281611df4565b806001600160a01b03166113646115a7565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b6001600160a01b039182166000908152609b6020908152604080832093909416825291909152205490565b60a05481565b60008051602061216183398151915280546002811415611425576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561143233611d88565b611483576040805162461bcd60e51b815260206004820152601960248201527f4163636f756e7420686173206e6f74206f70746564206f757400000000000000604482015290519081900360640190fd5b60006114bf61149133611af8565b609f54336000908152609d60205260409020546114b39163ffffffff611e1816565b9063ffffffff611e7116565b90506114dc6114cd33610e9a565b60a0549063ffffffff6115cc16565b60a055336000908152609d60205260409020819055609e54611504908263ffffffff6117ad16565b609e55505033600090815260a260209081526040808320805460ff1916600217905560a190915281205560019055565b6001600160a01b0381166000908152609d6020526040812054819061155884611af8565b91509150915091565b303b1590565b825161157a9060979060208601906120c8565b50815161158e9060989060208501906120c8565b506099805460ff191660ff929092169190911790555050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600061160e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611eb3565b9392505050565b600061162083611d88565b9050600061162d85611d88565b9050600061164a61163d86611af8565b859063ffffffff611f4a16565b9050600061166761165a88611af8565b869063ffffffff611f4a16565b90506116d8816040518060400160405280601f81526020017f5472616e7366657220616d6f756e7420657863656564732062616c616e636500815250609d60008b6001600160a01b03166001600160a01b0316815260200190815260200160002054611eb39092919063ffffffff16565b6001600160a01b038089166000908152609d6020526040808220939093559088168152205461170d908363ffffffff6117ad16565b6001600160a01b0387166000908152609d6020526040902055838015611731575082155b156117675760a054611749908663ffffffff6117ad16565b60a055609e5461175f908263ffffffff6115cc16565b609e556117a4565b831580156117725750825b156117a45760a05461178a908663ffffffff6115cc16565b60a055609e546117a0908363ffffffff6117ad16565b609e555b50505050505050565b60008282018381101561160e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008061182284670de0b6b3a764000063ffffffff611e1816565b9050611834818463ffffffff611e7116565b949350505050565b60008051602061216183398151915280546002811415611894576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b0384166118f3576040805162461bcd60e51b815260206004820152601860248201527f4d696e7420746f20746865207a65726f20616464726573730000000000000000604482015290519081900360640190fd5b60006118fe85611d88565b9050600061190e61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915061193a908263ffffffff6117ad16565b6001600160a01b0387166000908152609d602052604090205581156119745760a05461196c908663ffffffff6117ad16565b60a05561198b565b609e54611987908263ffffffff6117ad16565b609e555b609a5461199e908663ffffffff6117ad16565b609a8190556001600160801b03116119ea576040805162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b604482015290519081900360640190fd5b6040805186815290516001600160a01b038816916000916000805160206121d08339815191529181900360200190a350506001825550505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116611aa5576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316611ab76115a7565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3611af581611f5f565b50565b6001600160a01b038116600090815260a1602052604081205415611b3557506001600160a01b038116600090815260a16020526040902054610ef3565b50609f54610ef3565b60008051602061216183398151915280546002811415611b96576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b038416611bf5576040805162461bcd60e51b815260206004820152601a60248201527f4275726e2066726f6d20746865207a65726f2061646472657373000000000000604482015290519081900360640190fd5b82611bff57611d7f565b6000611c0a85611d88565b90506000611c1a61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915080821480611c4657508160018203145b15611c69576001600160a01b0387166000908152609d6020526040812055611cfe565b81811115611cb8576001600160a01b0387166000908152609d6020526040902054611c9a908363ffffffff6115cc16565b6001600160a01b0388166000908152609d6020526040902055611cfe565b6040805162461bcd60e51b815260206004820152601660248201527552656d6f766520657863656564732062616c616e636560501b604482015290519081900360640190fd5b8215611d1f5760a054611d17908763ffffffff6115cc16565b60a055611d36565b609e54611d32908363ffffffff6115cc16565b609e555b609a54611d49908763ffffffff6115cc16565b609a556040805187815290516000916001600160a01b038a16916000805160206121d08339815191529181900360200190a35050505b50600190555050565b600080611d9483611f83565b9050808015611dc757506001600160a01b038316600090815260a2602052604081205460ff166002811115611dc557fe5b145b15611dd557611dd583611fbc565b50506001600160a01b0316600090815260a16020526040902054151590565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600082611e27575060006108fd565b82820282848281611e3457fe5b041461160e5760405162461bcd60e51b81526004018080602001828103825260218152602001806121816021913960400191505060405180910390fd5b600061160e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612035565b60008184841115611f425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f07578181015183820152602001611eef565b50505050905090810190601f168015611f345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061160e8383670de0b6b3a764000061209a565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611834575050151592915050565b6001600160a01b038116600090815260a16020526040902054611af557609f546001600160a01b038216600090815260a1602052604090205561200161126582610e9a565b60a0556001600160a01b0381166000908152609d6020526040902054609e5461202f9163ffffffff6115cc16565b609e5550565b600081836120845760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611f07578181015183820152602001611eef565b50600083858161209057fe5b0495945050505050565b6000806120ad858563ffffffff611e1816565b90506120bf818463ffffffff611e7116565b95945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061210957805160ff1916838001178555612136565b82800160010185558215612136579182015b8281111561213657825182559160200191906001019061211b565b50612142929150612146565b5090565b6106f691905b80821115612142576000815560010161214c56fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158205227783b0c43cba340cfbfe748686c3a494c001c4b18954f2047eaf486aec56b64736f6c634300050b0032", + "solcInputHash": "c2ea476b4aec8b6a8c5cdeb6adf2172f", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"string\",\"name\":\"_nameArg\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"_symbolArg\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_vaultAddress\",\"type\":\"address\"}],\"name\":\"initialize\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasingCredits\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_newTotalSupply\",\"type\":\"uint256\"}],\"name\":\"changeSupply\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"_totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rebaseState\",\"outputs\":[{\"internalType\":\"enum OUSD.RebaseOptions\",\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonRebasingCreditsPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"rebasingCreditsPerToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebaseOptOut\",\"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\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"nonRebasingSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"rebaseOptIn\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"}],\"name\":\"creditsBalanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalSupply\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rebasingCredits\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rebasingCreditsPerToken\",\"type\":\"uint256\"}],\"name\":\"TotalSupplyUpdated\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"}],\"devdoc\":{\"methods\":{\"allowance(address,address)\":{\"details\":\"Function to check the _amount of tokens that an owner has allowed to a _spender.\",\"params\":{\"_owner\":\"The address which owns the funds.\",\"_spender\":\"The address which will spend the funds.\"},\"return\":\"The number of tokens still available for the _spender.\"},\"approve(address,uint256)\":{\"details\":\"Approve the passed address to spend the specified _amount of tokens on behalf of msg.sender. This method is included for ERC20 compatibility. increaseAllowance and decreaseAllowance should be used instead. Changing an allowance with this method brings the risk that someone may transfer both the old and the new allowance - if they are both greater than zero - if a transfer transaction is mined before the later approve() call is mined.\",\"params\":{\"_spender\":\"The address which will spend the funds.\",\"_value\":\"The _amount of tokens to be spent.\"}},\"balanceOf(address)\":{\"details\":\"Gets the balance of the specified address.\",\"params\":{\"_account\":\"Address to query the balance of.\"},\"return\":\"A uint256 representing the _amount of base units owned by the specified address.\"},\"burn(address,uint256)\":{\"details\":\"Burns tokens, decreasing totalSupply.\"},\"changeSupply(uint256)\":{\"details\":\"Modify the supply without minting new tokens. This uses a change in the exchange rate between \\\"credits\\\" and OUSD tokens to change balances.\",\"params\":{\"_newTotalSupply\":\"New total supply of OUSD.\"},\"return\":\"uint256 representing the new total supply.\"},\"claimGovernance()\":{\"details\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"creditsBalanceOf(address)\":{\"details\":\"Gets the credits balance of the specified address.\",\"params\":{\"_account\":\"The address to query the balance of.\"},\"return\":\"(uint256, uint256) Credit balance and credits per token of the address\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). * Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. * NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Decrease the _amount of tokens that an owner has allowed to a _spender.\",\"params\":{\"_spender\":\"The address which will spend the funds.\",\"_subtractedValue\":\"The _amount of tokens to decrease the allowance by.\"}},\"governor()\":{\"details\":\"Returns the address of the current Governor.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Increase the _amount of tokens that an owner has allowed to a _spender. This method should be used instead of approve() to avoid the double approval vulnerability described above.\",\"params\":{\"_addedValue\":\"The _amount of tokens to increase the allowance by.\",\"_spender\":\"The address which will spend the funds.\"}},\"isGovernor()\":{\"details\":\"Returns true if the caller is the current Governor.\"},\"mint(address,uint256)\":{\"details\":\"Mints new tokens, increasing totalSupply.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"rebaseOptIn()\":{\"details\":\"Add a contract address to the non rebasing exception list. I.e. the address's balance will be part of rebases so the account will be exposed to upside and downside.\"},\"rebaseOptOut()\":{\"details\":\"Remove a contract address to the non rebasing exception list.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"return\":\"The total supply of OUSD.\"},\"transfer(address,uint256)\":{\"details\":\"Transfer tokens to a specified address.\",\"params\":{\"_to\":\"the address to transfer to.\",\"_value\":\"the _amount to be transferred.\"},\"return\":\"true on success.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"Transfer tokens from one address to another.\",\"params\":{\"_from\":\"The address you want to send tokens from.\",\"_to\":\"The address you want to transfer to.\",\"_value\":\"The _amount of tokens to be transferred.\"}},\"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\":{},\"notice\":\"NOTE that this is an ERC20 token but the invariant that the sum of balanceOf(x) for all x is not >= totalSupply(). This is a consequence of the rebasing design. Any integrations with OUSD should be aware.\"}},\"settings\":{\"compilationTarget\":{\"contracts/token/OUSD.sol\":\"OUSD\"},\"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/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/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 if (_creditBalances[_account] == 0) {\\n // Since there is no existing balance, we can directly set to\\n // high resolution, and do not have to do any other bookkeeping\\n nonRebasingCreditsPerToken[_account] = 1e27;\\n } else {\\n // Migrate an existing account:\\n\\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(\\n _creditBalances[_account]\\n );\\n }\\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\":\"0x24b5da93d2279b02336983588dada1fecd3360b5df7074d83f2a79170f4216df\"},\"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\"}},\"version\":1}", + "bytecode": "0x6080604052609c80546001600160a01b031916905562000028336001600160e01b036200008116565b6200003b6001600160e01b036200009416565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000a8565b6000805160206200235583398151915255565b600080516020620023558339815191525490565b61229d80620000b86000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80635d36b19011610104578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105e5578063e696393a14610613578063f51b0fd41461061b578063f9854bfc14610623576101cf565b8063a9059cbb14610583578063c2376dff146105af578063c7af3352146105b7578063d38bfff4146105bf576101cf565b806370a08231116100de57806370a08231146104fd57806395d89b41146105235780639dc29fac1461052b578063a457c2d714610557576101cf565b80635d36b190146104c7578063609350cd146104cf5780636691cb3d146104f5576101cf565b8063313ce567116101715780633eaaf86b1161014b5780633eaaf86b1461044157806340c10f1914610449578063430bf08a14610475578063456ee2861461047d576101cf565b8063313ce567146103da57806339509351146103f857806339a7919f14610424576101cf565b8063095ea7b3116101ad578063095ea7b3146103385780630c340a241461037857806318160ddd1461039c57806323b872dd146103a4576101cf565b806306fdde03146101d4578063077f224a14610251578063077f22b71461031e575b600080fd5b6101dc610662565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61031c6004803603606081101561026757600080fd5b81019060208101813564010000000081111561028257600080fd5b82018360208201111561029457600080fd5b803590602001918460018302840111640100000000831117156102b657600080fd5b9193909290916020810190356401000000008111156102d457600080fd5b8201836020820111156102e657600080fd5b8035906020019184600183028401116401000000008311171561030857600080fd5b9193509150356001600160a01b03166106f9565b005b610326610896565b60408051918252519081900360200190f35b6103646004803603604081101561034e57600080fd5b506001600160a01b03813516906020013561089c565b604080519115158252519081900360200190f35b610380610903565b604080516001600160a01b039092168252519081900360200190f35b610326610912565b610364600480360360608110156103ba57600080fd5b506001600160a01b03813581169160208101359091169060400135610918565b6103e2610a73565b6040805160ff9092168252519081900360200190f35b6103646004803603604081101561040e57600080fd5b506001600160a01b038135169060200135610a7c565b61031c6004803603602081101561043a57600080fd5b5035610b15565b610326610d8f565b61031c6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610d95565b610380610dfc565b6104a36004803603602081101561049357600080fd5b50356001600160a01b0316610e0b565b604051808260028111156104b357fe5b60ff16815260200191505060405180910390f35b61031c610e20565b610326600480360360208110156104e557600080fd5b50356001600160a01b0316610e82565b610326610e94565b6103266004803603602081101561051357600080fd5b50356001600160a01b0316610e9a565b6101dc610ef8565b61031c6004803603604081101561054157600080fd5b506001600160a01b038135169060200135610f59565b6103646004803603604081101561056d57600080fd5b506001600160a01b038135169060200135610fbc565b6103646004803603604081101561059957600080fd5b506001600160a01b0381351690602001356110ab565b61031c6111a2565b6103646112cd565b61031c600480360360208110156105d557600080fd5b50356001600160a01b03166112f0565b610326600480360360408110156105fb57600080fd5b506001600160a01b038135811691602001351661139c565b6103266113c7565b61031c6113cd565b6106496004803603602081101561063957600080fd5b50356001600160a01b0316611534565b6040805192835260208301919091528051918290030190f35b60978054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b820191906000526020600020905b8154815290600101906020018083116106d157829003601f168201915b505050505090505b90565b6107016112cd565b610752576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b600054610100900460ff168061076b575061076b611561565b80610779575060005460ff16155b6107b45760405162461bcd60e51b815260040180806020018281038252602e8152602001806121eb602e913960400191505060405180910390fd5b600054610100900460ff161580156107df576000805460ff1961ff0019909116610100171660011790555b61085586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525060129250611567915050565b670de0b6b3a7640000609f55609c80546001600160a01b0319166001600160a01b038416179055801561088e576000805461ff00191690555b505050505050565b609e5481565b336000818152609b602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090d6115a7565b905090565b609a5490565b60006001600160a01b038316610970576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61097984610e9a565b8211156109cd576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b6001600160a01b0384166000908152609b60209081526040808320338452909152902054610a01908363ffffffff6115cc16565b6001600160a01b0385166000908152609b60209081526040808320338452909152902055610a30848484611615565b826001600160a01b0316846001600160a01b0316600080516020612219833981519152846040518082815260200191505060405180910390a35060019392505050565b60995460ff1690565b336000908152609b602090815260408083206001600160a01b0386168452909152812054610ab0908363ffffffff6117ad16565b336000818152609b602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b609c546001600160a01b03163314610b6e576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b6000805160206121aa83398151915280546002811415610bc6576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556000609a5411610c21576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420696e637265617365203020737570706c790000000000000000604482015290519081900360640190fd5b82609a541415610c7757609a54609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a1610d87565b6001600160801b038311610c8b5782610c94565b6001600160801b035b609a81905560a054610cbe91610caf9163ffffffff6115cc16565b609e549063ffffffff61180716565b609f819055610d14576040805162461bcd60e51b815260206004820152601860248201527f496e76616c6964206368616e676520696e20737570706c790000000000000000604482015290519081900360640190fd5b610d3d60a054610d31609f54609e5461180790919063ffffffff16565b9063ffffffff6117ad16565b609a819055609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a15b506001905550565b609a5481565b609c546001600160a01b03163314610dee576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df8828261183c565b5050565b609c546001600160a01b031681565b60a26020526000908152604090205460ff1681565b610e28611a25565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b81526004018080602001828103825260308152602001806122396030913960400191505060405180910390fd5b610e8033611a4a565b565b60a16020526000908152604090205481565b609f5481565b6001600160a01b0381166000908152609d6020526040812054610ebf57506000610ef3565b610ef0610ecb83611af8565b6001600160a01b0384166000908152609d60205260409020549063ffffffff61180716565b90505b919050565b60988054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b609c546001600160a01b03163314610fb2576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df88282611b3e565b336000908152609b602090815260408083206001600160a01b038616845290915281205480831061101057336000908152609b602090815260408083206001600160a01b0388168452909152812055611045565b611020818463ffffffff6115cc16565b336000908152609b602090815260408083206001600160a01b03891684529091529020555b336000818152609b602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60006001600160a01b038316611103576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61110c33610e9a565b821115611160576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b61116b338484611615565b6040805183815290516001600160a01b0385169133916000805160206122198339815191529181900360200190a350600192915050565b6000805160206121aa833981519152805460028114156111fa576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561120733611d88565b15611259576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e7420686173206e6f74206f7074656420696e0000000000000000604482015290519081900360640190fd5b61127461126533610e9a565b60a0549063ffffffff6117ad16565b60a055609f5433600090815260a16020908152604080832093909355609d90522054609e546112a89163ffffffff6115cc16565b609e555033600090815260a260205260409020805460ff191660019081179091559055565b60006112d76115a7565b6001600160a01b0316336001600160a01b031614905090565b6112f86112cd565b611349576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61135281611df4565b806001600160a01b03166113646115a7565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b6001600160a01b039182166000908152609b6020908152604080832093909416825291909152205490565b60a05481565b6000805160206121aa83398151915280546002811415611425576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561143233611d88565b611483576040805162461bcd60e51b815260206004820152601960248201527f4163636f756e7420686173206e6f74206f70746564206f757400000000000000604482015290519081900360640190fd5b60006114bf61149133611af8565b609f54336000908152609d60205260409020546114b39163ffffffff611e1816565b9063ffffffff611e7116565b90506114dc6114cd33610e9a565b60a0549063ffffffff6115cc16565b60a055336000908152609d60205260409020819055609e54611504908263ffffffff6117ad16565b609e55505033600090815260a260209081526040808320805460ff1916600217905560a190915281205560019055565b6001600160a01b0381166000908152609d6020526040812054819061155884611af8565b91509150915091565b303b1590565b825161157a906097906020860190612111565b50815161158e906098906020850190612111565b506099805460ff191660ff929092169190911790555050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600061160e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611eb3565b9392505050565b600061162083611d88565b9050600061162d85611d88565b9050600061164a61163d86611af8565b859063ffffffff611f4a16565b9050600061166761165a88611af8565b869063ffffffff611f4a16565b90506116d8816040518060400160405280601f81526020017f5472616e7366657220616d6f756e7420657863656564732062616c616e636500815250609d60008b6001600160a01b03166001600160a01b0316815260200190815260200160002054611eb39092919063ffffffff16565b6001600160a01b038089166000908152609d6020526040808220939093559088168152205461170d908363ffffffff6117ad16565b6001600160a01b0387166000908152609d6020526040902055838015611731575082155b156117675760a054611749908663ffffffff6117ad16565b60a055609e5461175f908263ffffffff6115cc16565b609e556117a4565b831580156117725750825b156117a45760a05461178a908663ffffffff6115cc16565b60a055609e546117a0908363ffffffff6117ad16565b609e555b50505050505050565b60008282018381101561160e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008061182284670de0b6b3a764000063ffffffff611e1816565b9050611834818463ffffffff611e7116565b949350505050565b6000805160206121aa83398151915280546002811415611894576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b0384166118f3576040805162461bcd60e51b815260206004820152601860248201527f4d696e7420746f20746865207a65726f20616464726573730000000000000000604482015290519081900360640190fd5b60006118fe85611d88565b9050600061190e61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915061193a908263ffffffff6117ad16565b6001600160a01b0387166000908152609d602052604090205581156119745760a05461196c908663ffffffff6117ad16565b60a05561198b565b609e54611987908263ffffffff6117ad16565b609e555b609a5461199e908663ffffffff6117ad16565b609a8190556001600160801b03116119ea576040805162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b604482015290519081900360640190fd5b6040805186815290516001600160a01b038816916000916000805160206122198339815191529181900360200190a350506001825550505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116611aa5576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316611ab76115a7565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3611af581611f5f565b50565b6001600160a01b038116600090815260a1602052604081205415611b3557506001600160a01b038116600090815260a16020526040902054610ef3565b50609f54610ef3565b6000805160206121aa83398151915280546002811415611b96576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b038416611bf5576040805162461bcd60e51b815260206004820152601a60248201527f4275726e2066726f6d20746865207a65726f2061646472657373000000000000604482015290519081900360640190fd5b82611bff57611d7f565b6000611c0a85611d88565b90506000611c1a61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915080821480611c4657508160018203145b15611c69576001600160a01b0387166000908152609d6020526040812055611cfe565b81811115611cb8576001600160a01b0387166000908152609d6020526040902054611c9a908363ffffffff6115cc16565b6001600160a01b0388166000908152609d6020526040902055611cfe565b6040805162461bcd60e51b815260206004820152601660248201527552656d6f766520657863656564732062616c616e636560501b604482015290519081900360640190fd5b8215611d1f5760a054611d17908763ffffffff6115cc16565b60a055611d36565b609e54611d32908363ffffffff6115cc16565b609e555b609a54611d49908763ffffffff6115cc16565b609a556040805187815290516000916001600160a01b038a16916000805160206122198339815191529181900360200190a35050505b50600190555050565b600080611d9483611f83565b9050808015611dc757506001600160a01b038316600090815260a2602052604081205460ff166002811115611dc557fe5b145b15611dd557611dd583611fbc565b50506001600160a01b0316600090815260a16020526040902054151590565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600082611e27575060006108fd565b82820282848281611e3457fe5b041461160e5760405162461bcd60e51b81526004018080602001828103825260218152602001806121ca6021913960400191505060405180910390fd5b600061160e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061207e565b60008184841115611f425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f07578181015183820152602001611eef565b50505050905090810190601f168015611f345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061160e8383670de0b6b3a76400006120e3565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611834575050151592915050565b6001600160a01b038116600090815260a16020526040902054611af5576001600160a01b0381166000908152609d6020526040902054612022576001600160a01b038116600090815260a1602052604090206b033b2e3c9fd0803ce80000009055611af5565b609f546001600160a01b038216600090815260a1602052604090205561204a61126582610e9a565b60a0556001600160a01b0381166000908152609d6020526040902054609e546120789163ffffffff6115cc16565b609e5550565b600081836120cd5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611f07578181015183820152602001611eef565b5060008385816120d957fe5b0495945050505050565b6000806120f6858563ffffffff611e1816565b9050612108818463ffffffff611e7116565b95945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061215257805160ff191683800117855561217f565b8280016001018555821561217f579182015b8281111561217f578251825591602001919060010190612164565b5061218b92915061218f565b5090565b6106f691905b8082111561218b576000815560010161219556fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820cd6d1104ba3da6a25fe62bc6f9a1a33a9dda54786ec6f85e49ec318bf70a0c5664736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80635d36b19011610104578063a9059cbb116100a2578063dd62ed3e11610071578063dd62ed3e146105e5578063e696393a14610613578063f51b0fd41461061b578063f9854bfc14610623576101cf565b8063a9059cbb14610583578063c2376dff146105af578063c7af3352146105b7578063d38bfff4146105bf576101cf565b806370a08231116100de57806370a08231146104fd57806395d89b41146105235780639dc29fac1461052b578063a457c2d714610557576101cf565b80635d36b190146104c7578063609350cd146104cf5780636691cb3d146104f5576101cf565b8063313ce567116101715780633eaaf86b1161014b5780633eaaf86b1461044157806340c10f1914610449578063430bf08a14610475578063456ee2861461047d576101cf565b8063313ce567146103da57806339509351146103f857806339a7919f14610424576101cf565b8063095ea7b3116101ad578063095ea7b3146103385780630c340a241461037857806318160ddd1461039c57806323b872dd146103a4576101cf565b806306fdde03146101d4578063077f224a14610251578063077f22b71461031e575b600080fd5b6101dc610662565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102165781810151838201526020016101fe565b50505050905090810190601f1680156102435780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61031c6004803603606081101561026757600080fd5b81019060208101813564010000000081111561028257600080fd5b82018360208201111561029457600080fd5b803590602001918460018302840111640100000000831117156102b657600080fd5b9193909290916020810190356401000000008111156102d457600080fd5b8201836020820111156102e657600080fd5b8035906020019184600183028401116401000000008311171561030857600080fd5b9193509150356001600160a01b03166106f9565b005b610326610896565b60408051918252519081900360200190f35b6103646004803603604081101561034e57600080fd5b506001600160a01b03813516906020013561089c565b604080519115158252519081900360200190f35b610380610903565b604080516001600160a01b039092168252519081900360200190f35b610326610912565b610364600480360360608110156103ba57600080fd5b506001600160a01b03813581169160208101359091169060400135610918565b6103e2610a73565b6040805160ff9092168252519081900360200190f35b6103646004803603604081101561040e57600080fd5b506001600160a01b038135169060200135610a7c565b61031c6004803603602081101561043a57600080fd5b5035610b15565b610326610d8f565b61031c6004803603604081101561045f57600080fd5b506001600160a01b038135169060200135610d95565b610380610dfc565b6104a36004803603602081101561049357600080fd5b50356001600160a01b0316610e0b565b604051808260028111156104b357fe5b60ff16815260200191505060405180910390f35b61031c610e20565b610326600480360360208110156104e557600080fd5b50356001600160a01b0316610e82565b610326610e94565b6103266004803603602081101561051357600080fd5b50356001600160a01b0316610e9a565b6101dc610ef8565b61031c6004803603604081101561054157600080fd5b506001600160a01b038135169060200135610f59565b6103646004803603604081101561056d57600080fd5b506001600160a01b038135169060200135610fbc565b6103646004803603604081101561059957600080fd5b506001600160a01b0381351690602001356110ab565b61031c6111a2565b6103646112cd565b61031c600480360360208110156105d557600080fd5b50356001600160a01b03166112f0565b610326600480360360408110156105fb57600080fd5b506001600160a01b038135811691602001351661139c565b6103266113c7565b61031c6113cd565b6106496004803603602081101561063957600080fd5b50356001600160a01b0316611534565b6040805192835260208301919091528051918290030190f35b60978054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b820191906000526020600020905b8154815290600101906020018083116106d157829003601f168201915b505050505090505b90565b6107016112cd565b610752576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b600054610100900460ff168061076b575061076b611561565b80610779575060005460ff16155b6107b45760405162461bcd60e51b815260040180806020018281038252602e8152602001806121eb602e913960400191505060405180910390fd5b600054610100900460ff161580156107df576000805460ff1961ff0019909116610100171660011790555b61085586868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8a01819004810282018101909252888152925088915087908190840183828082843760009201919091525060129250611567915050565b670de0b6b3a7640000609f55609c80546001600160a01b0319166001600160a01b038416179055801561088e576000805461ff00191690555b505050505050565b609e5481565b336000818152609b602090815260408083206001600160a01b038716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b600061090d6115a7565b905090565b609a5490565b60006001600160a01b038316610970576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61097984610e9a565b8211156109cd576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b6001600160a01b0384166000908152609b60209081526040808320338452909152902054610a01908363ffffffff6115cc16565b6001600160a01b0385166000908152609b60209081526040808320338452909152902055610a30848484611615565b826001600160a01b0316846001600160a01b0316600080516020612219833981519152846040518082815260200191505060405180910390a35060019392505050565b60995460ff1690565b336000908152609b602090815260408083206001600160a01b0386168452909152812054610ab0908363ffffffff6117ad16565b336000818152609b602090815260408083206001600160a01b0389168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b609c546001600160a01b03163314610b6e576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b6000805160206121aa83398151915280546002811415610bc6576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556000609a5411610c21576040805162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420696e637265617365203020737570706c790000000000000000604482015290519081900360640190fd5b82609a541415610c7757609a54609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a1610d87565b6001600160801b038311610c8b5782610c94565b6001600160801b035b609a81905560a054610cbe91610caf9163ffffffff6115cc16565b609e549063ffffffff61180716565b609f819055610d14576040805162461bcd60e51b815260206004820152601860248201527f496e76616c6964206368616e676520696e20737570706c790000000000000000604482015290519081900360640190fd5b610d3d60a054610d31609f54609e5461180790919063ffffffff16565b9063ffffffff6117ad16565b609a819055609e54609f5460408051938452602084019290925282820152517f99e56f783b536ffacf422d59183ea321dd80dcd6d23daa13023e8afea38c3df19181900360600190a15b506001905550565b609a5481565b609c546001600160a01b03163314610dee576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df8828261183c565b5050565b609c546001600160a01b031681565b60a26020526000908152604090205460ff1681565b610e28611a25565b6001600160a01b0316336001600160a01b031614610e775760405162461bcd60e51b81526004018080602001828103825260308152602001806122396030913960400191505060405180910390fd5b610e8033611a4a565b565b60a16020526000908152604090205481565b609f5481565b6001600160a01b0381166000908152609d6020526040812054610ebf57506000610ef3565b610ef0610ecb83611af8565b6001600160a01b0384166000908152609d60205260409020549063ffffffff61180716565b90505b919050565b60988054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156106ee5780601f106106c3576101008083540402835291602001916106ee565b609c546001600160a01b03163314610fb2576040805162461bcd60e51b815260206004820152601760248201527610d85b1b195c881a5cc81b9bdd081d1a194815985d5b1d604a1b604482015290519081900360640190fd5b610df88282611b3e565b336000908152609b602090815260408083206001600160a01b038616845290915281205480831061101057336000908152609b602090815260408083206001600160a01b0388168452909152812055611045565b611020818463ffffffff6115cc16565b336000908152609b602090815260408083206001600160a01b03891684529091529020555b336000818152609b602090815260408083206001600160a01b0389168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60006001600160a01b038316611103576040805162461bcd60e51b81526020600482015260186024820152775472616e7366657220746f207a65726f206164647265737360401b604482015290519081900360640190fd5b61110c33610e9a565b821115611160576040805162461bcd60e51b815260206004820152601d60248201527f5472616e736665722067726561746572207468616e2062616c616e6365000000604482015290519081900360640190fd5b61116b338484611615565b6040805183815290516001600160a01b0385169133916000805160206122198339815191529181900360200190a350600192915050565b6000805160206121aa833981519152805460028114156111fa576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561120733611d88565b15611259576040805162461bcd60e51b815260206004820152601860248201527f4163636f756e7420686173206e6f74206f7074656420696e0000000000000000604482015290519081900360640190fd5b61127461126533610e9a565b60a0549063ffffffff6117ad16565b60a055609f5433600090815260a16020908152604080832093909355609d90522054609e546112a89163ffffffff6115cc16565b609e555033600090815260a260205260409020805460ff191660019081179091559055565b60006112d76115a7565b6001600160a01b0316336001600160a01b031614905090565b6112f86112cd565b611349576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61135281611df4565b806001600160a01b03166113646115a7565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b6001600160a01b039182166000908152609b6020908152604080832093909416825291909152205490565b60a05481565b6000805160206121aa83398151915280546002811415611425576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b6002825561143233611d88565b611483576040805162461bcd60e51b815260206004820152601960248201527f4163636f756e7420686173206e6f74206f70746564206f757400000000000000604482015290519081900360640190fd5b60006114bf61149133611af8565b609f54336000908152609d60205260409020546114b39163ffffffff611e1816565b9063ffffffff611e7116565b90506114dc6114cd33610e9a565b60a0549063ffffffff6115cc16565b60a055336000908152609d60205260409020819055609e54611504908263ffffffff6117ad16565b609e55505033600090815260a260209081526040808320805460ff1916600217905560a190915281205560019055565b6001600160a01b0381166000908152609d6020526040812054819061155884611af8565b91509150915091565b303b1590565b825161157a906097906020860190612111565b50815161158e906098906020850190612111565b506099805460ff191660ff929092169190911790555050565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600061160e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611eb3565b9392505050565b600061162083611d88565b9050600061162d85611d88565b9050600061164a61163d86611af8565b859063ffffffff611f4a16565b9050600061166761165a88611af8565b869063ffffffff611f4a16565b90506116d8816040518060400160405280601f81526020017f5472616e7366657220616d6f756e7420657863656564732062616c616e636500815250609d60008b6001600160a01b03166001600160a01b0316815260200190815260200160002054611eb39092919063ffffffff16565b6001600160a01b038089166000908152609d6020526040808220939093559088168152205461170d908363ffffffff6117ad16565b6001600160a01b0387166000908152609d6020526040902055838015611731575082155b156117675760a054611749908663ffffffff6117ad16565b60a055609e5461175f908263ffffffff6115cc16565b609e556117a4565b831580156117725750825b156117a45760a05461178a908663ffffffff6115cc16565b60a055609e546117a0908363ffffffff6117ad16565b609e555b50505050505050565b60008282018381101561160e576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b60008061182284670de0b6b3a764000063ffffffff611e1816565b9050611834818463ffffffff611e7116565b949350505050565b6000805160206121aa83398151915280546002811415611894576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b0384166118f3576040805162461bcd60e51b815260206004820152601860248201527f4d696e7420746f20746865207a65726f20616464726573730000000000000000604482015290519081900360640190fd5b60006118fe85611d88565b9050600061190e61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915061193a908263ffffffff6117ad16565b6001600160a01b0387166000908152609d602052604090205581156119745760a05461196c908663ffffffff6117ad16565b60a05561198b565b609e54611987908263ffffffff6117ad16565b609e555b609a5461199e908663ffffffff6117ad16565b609a8190556001600160801b03116119ea576040805162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b604482015290519081900360640190fd5b6040805186815290516001600160a01b038816916000916000805160206122198339815191529181900360200190a350506001825550505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b038116611aa5576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b0316611ab76115a7565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3611af581611f5f565b50565b6001600160a01b038116600090815260a1602052604081205415611b3557506001600160a01b038116600090815260a16020526040902054610ef3565b50609f54610ef3565b6000805160206121aa83398151915280546002811415611b96576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b038416611bf5576040805162461bcd60e51b815260206004820152601a60248201527f4275726e2066726f6d20746865207a65726f2061646472657373000000000000604482015290519081900360640190fd5b82611bff57611d7f565b6000611c0a85611d88565b90506000611c1a61165a87611af8565b6001600160a01b0387166000908152609d602052604090205490915080821480611c4657508160018203145b15611c69576001600160a01b0387166000908152609d6020526040812055611cfe565b81811115611cb8576001600160a01b0387166000908152609d6020526040902054611c9a908363ffffffff6115cc16565b6001600160a01b0388166000908152609d6020526040902055611cfe565b6040805162461bcd60e51b815260206004820152601660248201527552656d6f766520657863656564732062616c616e636560501b604482015290519081900360640190fd5b8215611d1f5760a054611d17908763ffffffff6115cc16565b60a055611d36565b609e54611d32908363ffffffff6115cc16565b609e555b609a54611d49908763ffffffff6115cc16565b609a556040805187815290516000916001600160a01b038a16916000805160206122198339815191529181900360200190a35050505b50600190555050565b600080611d9483611f83565b9050808015611dc757506001600160a01b038316600090815260a2602052604081205460ff166002811115611dc557fe5b145b15611dd557611dd583611fbc565b50506001600160a01b0316600090815260a16020526040902054151590565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600082611e27575060006108fd565b82820282848281611e3457fe5b041461160e5760405162461bcd60e51b81526004018080602001828103825260218152602001806121ca6021913960400191505060405180910390fd5b600061160e83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061207e565b60008184841115611f425760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f07578181015183820152602001611eef565b50505050905090810190601f168015611f345780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b600061160e8383670de0b6b3a76400006120e3565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611834575050151592915050565b6001600160a01b038116600090815260a16020526040902054611af5576001600160a01b0381166000908152609d6020526040902054612022576001600160a01b038116600090815260a1602052604090206b033b2e3c9fd0803ce80000009055611af5565b609f546001600160a01b038216600090815260a1602052604090205561204a61126582610e9a565b60a0556001600160a01b0381166000908152609d6020526040902054609e546120789163ffffffff6115cc16565b609e5550565b600081836120cd5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315611f07578181015183820152602001611eef565b5060008385816120d957fe5b0495945050505050565b6000806120f6858563ffffffff611e1816565b9050612108818463ffffffff611e7116565b95945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061215257805160ff191683800117855561217f565b8280016001018555821561217f579182015b8281111561217f578251825591602001919060010190612164565b5061218b92915061218f565b5090565b6106f691905b8082111561218b576000815560010161219556fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a72315820cd6d1104ba3da6a25fe62bc6f9a1a33a9dda54786ec6f85e49ec318bf70a0c5664736f6c634300050b0032", "devdoc": { "methods": { "allowance(address,address)": { diff --git a/contracts/deployments/rinkeby/VaultCore.json b/contracts/deployments/rinkeby/VaultCore.json index 0eb7883f99..f055017a8b 100644 --- a/contracts/deployments/rinkeby/VaultCore.json +++ b/contracts/deployments/rinkeby/VaultCore.json @@ -1,5 +1,5 @@ { - "address": "0x24203812AcB90c75860db158c637C286259059ba", + "address": "0xe5Aeb6fa44234a0648373F6711498E5A2E27B51d", "abi": [ { "constant": true, @@ -816,42 +816,42 @@ "type": "event" } ], - "transactionHash": "0x3689f80b2d603cd88b5f7af77b1e9336ccbffdf9f8d205725c393f3fc4b689c2", + "transactionHash": "0xddd5ff1f8dfc7e7157ed209ca9d2655af80370f82aa46fd0873e718cbb85dc36", "receipt": { "to": null, "from": "0xD85A569F3C26f81070544451131c742283360400", - "contractAddress": "0x24203812AcB90c75860db158c637C286259059ba", + "contractAddress": "0xe5Aeb6fa44234a0648373F6711498E5A2E27B51d", "transactionIndex": 5, - "gasUsed": "3142306", - "logsBloom": "0x00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000020000000000000000000000004000000000000000400000000000000000000000000", - "blockHash": "0xbeffa9fba88cc7d1d78222552d454ff94de21ac8b80cd4dc41ff9b9d7d2f02ab", - "transactionHash": "0x3689f80b2d603cd88b5f7af77b1e9336ccbffdf9f8d205725c393f3fc4b689c2", + "gasUsed": "3105563", + "logsBloom": "0x00000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000004000000000000000000000400000000000000000000000000000000000000000400000000000000000000000000000080000000000000000000000000000000000000000000000010000000000040000000000000000000000000000020000000000000000000000000000000000000000400000000000000000000000000", + "blockHash": "0x90b0ca5636cae291e3f48bfe75f0a713b10c54b4ae829d3d387958989d6b0206", + "transactionHash": "0xddd5ff1f8dfc7e7157ed209ca9d2655af80370f82aa46fd0873e718cbb85dc36", "logs": [ { "transactionIndex": 5, - "blockNumber": 8292729, - "transactionHash": "0x3689f80b2d603cd88b5f7af77b1e9336ccbffdf9f8d205725c393f3fc4b689c2", - "address": "0x24203812AcB90c75860db158c637C286259059ba", + "blockNumber": 8868511, + "transactionHash": "0xddd5ff1f8dfc7e7157ed209ca9d2655af80370f82aa46fd0873e718cbb85dc36", + "address": "0xe5Aeb6fa44234a0648373F6711498E5A2E27B51d", "topics": [ "0xc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x000000000000000000000000d85a569f3c26f81070544451131c742283360400" ], "data": "0x", - "logIndex": 16, - "blockHash": "0xbeffa9fba88cc7d1d78222552d454ff94de21ac8b80cd4dc41ff9b9d7d2f02ab" + "logIndex": 5, + "blockHash": "0x90b0ca5636cae291e3f48bfe75f0a713b10c54b4ae829d3d387958989d6b0206" } ], - "blockNumber": 8292729, - "cumulativeGasUsed": "3817938", + "blockNumber": 8868511, + "cumulativeGasUsed": "3392449", "status": 1, "byzantium": true }, "args": [], - "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", + "solcInputHash": "c2ea476b4aec8b6a8c5cdeb6adf2172f", + "metadata": "{\"compiler\":{\"version\":\"0.5.11+commit.22be8592\"},\"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 if (_creditBalances[_account] == 0) {\\n // Since there is no existing balance, we can directly set to\\n // high resolution, and do not have to do any other bookkeeping\\n nonRebasingCreditsPerToken[_account] = 1e27;\\n } else {\\n // Migrate an existing account:\\n\\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(\\n _creditBalances[_account]\\n );\\n }\\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\":\"0x24b5da93d2279b02336983588dada1fecd3360b5df7074d83f2a79170f4216df\"},\"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 _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 // Calculate redemption outputs\\n (\\n uint256[] memory outputs,\\n uint256 _backingValue\\n ) = _calculateRedeemOutputs(_amount);\\n\\n // Check that OUSD is backed by enough assets\\n uint256 _totalSupply = oUSD.totalSupply();\\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 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 // 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 _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 (\\n uint256[] memory outputs,\\n uint256 totalValue\\n ) = _calculateRedeemOutputs(_amount);\\n return outputs;\\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, uint256 totalBalance)\\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 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\":\"0xb732b740a89c153297d79b32aa466722750da0ea5e698b4d952cd255ece6a6b3\"},\"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": "0x60806040526037805461ffff60a01b19167501000000000000000000000000000000000000000000179055603d80546001600160a01b0319908116909155603e805482169055603f8054909116905562000062336001600160e01b03620000bb16565b620000756001600160e01b03620000ce16565b6001600160a01b031660006001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3620000e2565b6000805160206200372983398151915255565b600080516020620037298339815191525490565b61363780620000f26000396000f3fe6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610ad1565b3480156102ed57600080fd5b50610233610ad7565b34801561030257600080fd5b5061030b610add565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610b3f565b34801561037c57600080fd5b5061025a610b45565b34801561039157600080fd5b50610233610b54565b3480156103a657600080fd5b506103af610b5a565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610b6a565b3480156103e457600080fd5b506102ca610b79565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610bdb565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610bec565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610c03565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610d35565b3480156104b057600080fd5b50610233610df4565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610dfa565b3480156104f857600080fd5b50610233610e18565b34801561050d57600080fd5b50610233610e1e565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610e24565b34801561055557600080fd5b506102ca610e3f565b34801561056a57600080fd5b506102ca610efa565b34801561057f57600080fd5b5061025a610faf565b34801561059457600080fd5b506103af610fbe565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b0316610fe1565b3480156105dc57600080fd5b5061023361108d565b3480156105f157600080fd5b506103af611097565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b9193509150356110a7565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b03166115a2565b60385481565b600061070c611663565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f9833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603754604080516315d5220f60e31b81526001600160a01b0388811660048301529151600093929092169163aea9107891602480820192602092909190829003018186803b1580156108d857600080fd5b505afa1580156108ec573d6000803e3d6000fd5b505050506040513d602081101561090257600080fd5b505190506305f5e10081111561091957506305f5e1005b600061092487611688565b9050600061093c87601284900363ffffffff61174216565b9050600061096661095485600a63ffffffff61174216565b8990600a86900a63ffffffff61179c16565b905086156109c357868110156109c3576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a1a5750603754600160a01b900460ff16155b15610a2757610a276117ca565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b508b9250610ab09150506001600160a01b03821633308c63ffffffff611af116565b603a548310610ac157610ac1611b51565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b3557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b17575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610b816120dc565b6001600160a01b0316336001600160a01b031614610bd05760405162461bcd60e51b81526004018080602001828103825260308152602001806135d36030913960400191505060405180910390fd5b610bd933612101565b565b6000610be6826121af565b92915050565b6060806000610bfa84612370565b50949350505050565b603754600160a81b900460ff1615610c53576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610cab576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603c54604080516370a0823160e01b81523360048201529051610d2d926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610cfb57600080fd5b505afa158015610d0f573d6000803e3d6000fd5b505050506040513d6020811015610d2557600080fd5b505184612631565b506001905550565b603754600160a81b900460ff1615610d85576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610ddd576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610deb8484612631565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610e8f576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610ee7576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610ef3611b51565b5060019055565b603754600160a01b900460ff1615610f4b576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610fa3576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610ef36117ca565b6037546001600160a01b031681565b6000610fc8611663565b6001600160a01b0316336001600160a01b031614905090565b610fe9610fbe565b61103a576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61104381612be5565b806001600160a01b0316611055611663565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612c09565b603754600160a81b900460ff1681565b603754600160a81b900460ff16156110f7576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f98339815191528054600281141561114f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282558584146111a7576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b60008060606111b582612c2a565b905060005b898110156113ee57603360008c8c848181106111d257fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff16611242576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061125057fe5b90506020020135116112a9576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b6034548110156113e557603481815481106112c357fe5b6000918252602090912001546001600160a01b03168c8c848181106112e457fe5b905060200201356001600160a01b03166001600160a01b031614156113dd57600061132f6034838154811061131557fe5b6000918252602090912001546001600160a01b0316611688565b9050600084838151811061133f57fe5b60200260200101519050670de0b6b3a76400008111156113645750670de0b6b3a76400005b61139c61138f836012038e8e8881811061137a57fe5b9050602002013561174290919063ffffffff16565b889063ffffffff612d4016565b96506113d86113cb8284600a0a8f8f898181106113b557fe5b9050602002013561179c9092919063ffffffff16565b879063ffffffff612d4016565b955050505b6001016112ac565b506001016111ba565b50851561144a578582101561144a576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b5483101580156114a15750603754600160a01b900460ff16155b156114ae576114ae6117ca565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b15801561150157600080fd5b505af1158015611515573d6000803e3d6000fd5b506000925050505b898110156115805760008b8b8381811061153357fe5b905060200201356001600160a01b0316905061157733308c8c8681811061155657fe5b90506020020135846001600160a01b0316611af1909392919063ffffffff16565b5060010161151d565b50603a54831061159257611592611b51565b5050506001825550505050505050565b6115aa610fbe565b6115fb576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61160481612da1565b61163f5760405162461bcd60e51b81526004018080602001828103825260248152602001806135196024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156116c457600080fd5b505afa1580156116d8573d6000803e3d6000fd5b505050506040513d60208110156116ee57600080fd5b505160ff16905060048110801590611707575060128111155b610be65760405162461bcd60e51b815260040180806020018281038252602981526020018061353d6029913960400191505060405180910390fd5b6000808260000b131561176d5761176683600084900b600a0a63ffffffff612ddd16565b9250611795565b60008260000b121561179557611792836000848103900b600a0a63ffffffff612e3616565b92505b5090919050565b6000806117af858563ffffffff612ddd16565b90506117c1818463ffffffff612e3616565b95945050505050565b603754600160a01b900460ff161561181b576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561186057600080fd5b505afa158015611874573d6000803e3d6000fd5b505050506040513d602081101561188a57600080fd5b50519050806118995750610bd9565b60006118a3612c09565b6042549091506001600160a01b031680158015906118c057508282115b15611a025760006118d7838563ffffffff612e7816565b905060006119026127106118f660435485612ddd90919063ffffffff16565b9063ffffffff612e3616565b90508082116119425760405162461bcd60e51b81526004018080602001828103825260228152602001806135876022913960400191505060405180910390fd5b80156119b657603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b15801561199d57600080fd5b505af11580156119b1573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5057600080fd5b505afa158015611a64573d6000803e3d6000fd5b505050506040513d6020811015611a7a57600080fd5b5051925082821115611aec57603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611ad357600080fd5b505af1158015611ae7573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611b4b908590612eba565b50505050565b6000611b5b613072565b905080611b685750610bd9565b6000611b7261316f565b90506000611b86838363ffffffff612d4016565b9050600082611bb257603954611bab90670de0b6b3a76400009063ffffffff612e7816565b9050611bfe565b611bcb846118f684603954612ddd90919063ffffffff16565b905080670de0b6b3a76400001115611bf557611bab670de0b6b3a76400008263ffffffff612e7816565b50505050610bd9565b80611c0c5750505050610bd9565b60005b603454811015611d9b57600060348281548110611c2857fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611c7b57600080fd5b505afa158015611c8f573d6000803e3d6000fd5b505050506040513d6020811015611ca557600080fd5b5051905080611cb5575050611d93565b6000611cc7828663ffffffff6131c116565b6001600160a01b03808516600090815260406020819052902054919250168015801590611cf45750600082115b15611d8e5780611d146001600160a01b038616828563ffffffff6131d616565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611d7457600080fd5b505af1158015611d88573d6000803e3d6000fd5b50505050505b505050505b600101611c0f565b5060005b60365481101561206d57600060368281548110611db857fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b158015611e0557600080fd5b505afa158015611e19573d6000803e3d6000fd5b505050506040513d6020811015611e2f57600080fd5b505190506001600160a01b03811615612063576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b158015611e7d57600080fd5b505afa158015611e91573d6000803e3d6000fd5b505050506040513d6020811015611ea757600080fd5b5051905080611f3657306001600160a01b0316630e5c011e60368681548110611ecc57fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b158015611f1957600080fd5b505af1158015611f2d573d6000803e3d6000fd5b50505050612061565b60008290506000816001600160a01b03166370a0823160368881548110611f5957fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015611fa757600080fd5b505afa158015611fbb573d6000803e3d6000fd5b505050506040513d6020811015611fd157600080fd5b5051905082811061205e57306001600160a01b0316630e5c011e60368881548110611ff857fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561204557600080fd5b505af1158015612059573d6000803e3d6000fd5b505050505b50505b505b5050600101611d9f565b50604260009054906101000a90046001600160a01b03166001600160a01b0316638119c0656040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120be57600080fd5b505af11580156120d2573d6000803e3d6000fd5b5050505050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b03811661215c576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661216e611663565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36121ac81613228565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156121fa57600080fd5b505afa15801561220e573d6000803e3d6000fd5b505050506040513d602081101561222457600080fd5b5051915060005b6036548110156123695760006036828154811061224457fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561229a57600080fd5b505afa1580156122ae573d6000803e3d6000fd5b505050506040513d60208110156122c457600080fd5b5051156123605761235d816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561232457600080fd5b505afa158015612338573d6000803e3d6000fd5b505050506040513d602081101561234e57600080fd5b5051859063ffffffff612d4016565b93505b5060010161222b565b5050919050565b606060008061237d610e1e565b9050606061238b6001612c2a565b90506060826040519080825280602002602001820160405280156123b9578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156123e8578160200160208202803883390190505b50905060008090508460405190808252806020026020018201604052801561241a578160200160208202803883390190505b50603854909750156124595760006124436127106118f66038548c612ddd90919063ffffffff16565b9050612455898263ffffffff612e7816565b9850505b60005b6034548110156125095760006124926034838154811061247857fe5b6000918252602090912001546001600160a01b03166121af565b905060006124a66034848154811061131557fe5b9050818684815181106124b557fe5b602002602001018181525050808584815181106124ce57fe5b60209081029190910101526124fd6124f083601284900363ffffffff61174216565b8a9063ffffffff612d4016565b9850505060010161245c565b5060005b6034548110156125ba57600085828151811061252557fe5b60200260200101519050670de0b6b3a764000081101561254a5750670de0b6b3a76400005b600061259c896118f68461259089888151811061256357fe5b60200260200101516012038b898151811061257a57fe5b602002602001015161174290919063ffffffff16565b9063ffffffff612ddd16565b90506125ae848263ffffffff612d4016565b9350505060010161250d565b5060006125cd898363ffffffff61324c16565b905060005b60345481101561262557612606886118f6848885815181106125f057fe5b6020026020010151612ddd90919063ffffffff16565b89828151811061261257fe5b60209081029190910101526001016125d2565b50505050505050915091565b60008211612686576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b6060600061269384612370565b915091506000603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126e757600080fd5b505afa1580156126fb573d6000803e3d6000fd5b505050506040513d602081101561271157600080fd5b5051604154909150156127ce576000612730828463ffffffff61324c16565b9050604154670de0b6b3a764000082116127615761275c670de0b6b3a76400008363ffffffff612e7816565b612779565b61277982670de0b6b3a764000063ffffffff612e7816565b11156127cc576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810187905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160005b603454811015612a9d5783818151811061282257fe5b60200260200101516000141561283757612a95565b60006034828154811061284657fe5b60009182526020909120015485516001600160a01b03909116915085908390811061286d57fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156128cb57600080fd5b505afa1580156128df573d6000803e3d6000fd5b505050506040513d60208110156128f557600080fd5b5051106129325761292d3386848151811061290c57fe5b6020026020010151836001600160a01b03166131d69092919063ffffffff16565b612a93565b6000604060006034858154811061294557fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612a52576000819050806001600160a01b031663d9caed12336034878154811061299a57fe5b9060005260206000200160009054906101000a90046001600160a01b03168a88815181106129c457fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612a3457600080fd5b505af1158015612a48573d6000803e3d6000fd5b5050505050612a91565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b60010161280c565b508315612b4b576000805b8451811015612af3576000612ac36034838154811061131557fe5b9050612ae8612adb8260120388858151811061257a57fe5b849063ffffffff612d4016565b925050600101612aa8565b5084811015612b49576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612b9e57600080fd5b505af1158015612bb2573d6000803e3d6000fd5b50505050603b5485118015612bd15750603754600160a01b900460ff16155b15612bde57612bde6117ca565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612c1661316f565b612c1e613072565b9063ffffffff612d4016565b6060612c34610e1e565b604051908082528060200260200182016040528015612c5d578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561236957612d21600a836001600160a01b031663aea9107860348581548110612c9b57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015612ce957600080fd5b505afa158015612cfd573d6000803e3d6000fd5b505050506040513d6020811015612d1357600080fd5b50519063ffffffff61174216565b838281518110612d2d57fe5b6020908102919091010152600101612c70565b600082820183811015612d9a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612dd557508115155b949350505050565b600082612dec57506000610be6565b82820282848281612df957fe5b0414612d9a5760405162461bcd60e51b81526004018080602001828103825260218152602001806135666021913960400191505060405180910390fd5b6000612d9a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613279565b6000612d9a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061331b565b612ecc826001600160a01b0316612da1565b612f1d576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612f5b5780518252601f199092019160209182019101612f3c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612fbd576040519150601f19603f3d011682016040523d82523d6000602084013e612fc2565b606091505b509150915081613019576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611b4b5780806020019051602081101561303557600080fd5b5051611b4b5760405162461bcd60e51b815260040180806020018281038252602a8152602001806135a9602a913960400191505060405180910390fd5b6000805b60345481101561316b5760006034828154811061308f57fe5b6000918252602082200154603480546001600160a01b0390921693506130b9918590811061131557fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b15801561310557600080fd5b505afa158015613119573d6000803e3d6000fd5b505050506040513d602081101561312f57600080fd5b5051905080156131605761315d61315082601285900363ffffffff61174216565b869063ffffffff612d4016565b94505b505050600101613076565b5090565b6000805b60365481101561316b576131b76131aa6036838154811061319057fe5b6000918252602090912001546001600160a01b0316613375565b839063ffffffff612d4016565b9150600101613173565b6000612d9a8383670de0b6b3a764000061179c565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611aec908490612eba565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061326784670de0b6b3a764000063ffffffff612ddd16565b9050612dd5818463ffffffff612e3616565b600081836133055760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156132ca5781810151838201526020016132b2565b50505050905090810190601f1680156132f75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161331157fe5b0495945050505050565b6000818484111561336d5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156132ca5781810151838201526020016132b2565b505050900390565b600081815b6034548110156123695760006133966034838154811061131557fe5b9050826001600160a01b031663aa388af6603484815481106133b457fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561340257600080fd5b505afa158015613416573d6000803e3d6000fd5b505050506040513d602081101561342c57600080fd5b5051156134ef576000836001600160a01b0316635f5152266034858154811061345157fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561349f57600080fd5b505afa1580156134b3573d6000803e3d6000fd5b505050506040513d60208110156134c957600080fd5b5051905080156134ed576134ea61315082601285900363ffffffff61174216565b94505b505b5060010161337a56fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158203f7824d3dfb9099003a39f9d314f7e755aeb69e5e84049357c6b4bf3ae75ec8964736f6c634300050b00327bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a", + "deployedBytecode": "0x6080604052600436106101d85760003560e01c80637136a7a611610102578063af14052c11610095578063d4c3eea011610064578063d4c3eea0146105d0578063e6cc5432146105e5578063f0efb4c7146105fa578063fc0cfeee146106c9576101d8565b8063af14052c1461055e578063b888879e14610573578063c7af335214610588578063d38bfff41461059d576101d8565b80639fa1826e116100d15780639fa1826e146104ec578063a0aead4d14610501578063a403e4d514610516578063abaa991614610549576101d8565b80637136a7a61461044a5780637cbc2373146104745780638e510b52146104a45780639be918e6146104b9576101d8565b806331e19cfa1161017a578063570d8e1d11610149578063570d8e1d146103c35780635d36b190146103d85780635f515226146103ed57806367bd7ba314610420576101d8565b806331e19cfa1461035b57806349c1d54d1461037057806352d38e5d1461038557806353ca9f241461039a576101d8565b8063156e29f6116101b6578063156e29f61461028b5780631edfe3da146102cc578063207134b0146102e15780632acada4d146102f6576101d8565b806309f6442c1461021e5780630c340a2414610245578063128a8b0514610276575b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9366000803760008036600084545af43d6000803e808015610219573d6000f35b3d6000fd5b34801561022a57600080fd5b506102336106fc565b60408051918252519081900360200190f35b34801561025157600080fd5b5061025a610702565b604080516001600160a01b039092168252519081900360200190f35b34801561028257600080fd5b5061025a610711565b34801561029757600080fd5b506102ca600480360360608110156102ae57600080fd5b506001600160a01b038135169060208101359060400135610720565b005b3480156102d857600080fd5b50610233610ad1565b3480156102ed57600080fd5b50610233610ad7565b34801561030257600080fd5b5061030b610add565b60408051602080825283518183015283519192839290830191858101910280838360005b8381101561034757818101518382015260200161032f565b505050509050019250505060405180910390f35b34801561036757600080fd5b50610233610b3f565b34801561037c57600080fd5b5061025a610b45565b34801561039157600080fd5b50610233610b54565b3480156103a657600080fd5b506103af610b5a565b604080519115158252519081900360200190f35b3480156103cf57600080fd5b5061025a610b6a565b3480156103e457600080fd5b506102ca610b79565b3480156103f957600080fd5b506102336004803603602081101561041057600080fd5b50356001600160a01b0316610bdb565b34801561042c57600080fd5b5061030b6004803603602081101561044357600080fd5b5035610bec565b34801561045657600080fd5b506102ca6004803603602081101561046d57600080fd5b5035610c03565b34801561048057600080fd5b506102ca6004803603604081101561049757600080fd5b5080359060200135610d35565b3480156104b057600080fd5b50610233610df4565b3480156104c557600080fd5b506103af600480360360208110156104dc57600080fd5b50356001600160a01b0316610dfa565b3480156104f857600080fd5b50610233610e18565b34801561050d57600080fd5b50610233610e1e565b34801561052257600080fd5b5061025a6004803603602081101561053957600080fd5b50356001600160a01b0316610e24565b34801561055557600080fd5b506102ca610e3f565b34801561056a57600080fd5b506102ca610efa565b34801561057f57600080fd5b5061025a610faf565b34801561059457600080fd5b506103af610fbe565b3480156105a957600080fd5b506102ca600480360360208110156105c057600080fd5b50356001600160a01b0316610fe1565b3480156105dc57600080fd5b5061023361108d565b3480156105f157600080fd5b506103af611097565b34801561060657600080fd5b506102ca6004803603606081101561061d57600080fd5b81019060208101813564010000000081111561063857600080fd5b82018360208201111561064a57600080fd5b8035906020019184602083028401116401000000008311171561066c57600080fd5b91939092909160208101903564010000000081111561068a57600080fd5b82018360208201111561069c57600080fd5b803590602001918460208302840111640100000000831117156106be57600080fd5b9193509150356110a7565b3480156106d557600080fd5b506102ca600480360360208110156106ec57600080fd5b50356001600160a01b03166115a2565b60385481565b600061070c611663565b905090565b603e546001600160a01b031681565b603754600160a81b900460ff1615610770576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f9833981519152805460028114156107c8576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282556001600160a01b03851660009081526033602052604090205460ff16610832576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b60008411610887576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b603754604080516315d5220f60e31b81526001600160a01b0388811660048301529151600093929092169163aea9107891602480820192602092909190829003018186803b1580156108d857600080fd5b505afa1580156108ec573d6000803e3d6000fd5b505050506040513d602081101561090257600080fd5b505190506305f5e10081111561091957506305f5e1005b600061092487611688565b9050600061093c87601284900363ffffffff61174216565b9050600061096661095485600a63ffffffff61174216565b8990600a86900a63ffffffff61179c16565b905086156109c357868110156109c3576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810183905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b548210158015610a1a5750603754600160a01b900460ff16155b15610a2757610a276117ca565b603c54604080516340c10f1960e01b81523360048201526024810184905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b158015610a7a57600080fd5b505af1158015610a8e573d6000803e3d6000fd5b508b9250610ab09150506001600160a01b03821633308c63ffffffff611af116565b603a548310610ac157610ac1611b51565b5050505050600182555050505050565b60395481565b60435481565b60606034805480602002602001604051908101604052809291908181526020018280548015610b3557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610b17575b5050505050905090565b60365490565b6042546001600160a01b031681565b603b5481565b603754600160a01b900460ff1681565b603f546001600160a01b031681565b610b816120dc565b6001600160a01b0316336001600160a01b031614610bd05760405162461bcd60e51b81526004018080602001828103825260308152602001806135d36030913960400191505060405180910390fd5b610bd933612101565b565b6000610be6826121af565b92915050565b6060806000610bfa84612370565b50949350505050565b603754600160a81b900460ff1615610c53576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610cab576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255603c54604080516370a0823160e01b81523360048201529051610d2d926001600160a01b0316916370a08231916024808301926020929190829003018186803b158015610cfb57600080fd5b505afa158015610d0f573d6000803e3d6000fd5b505050506040513d6020811015610d2557600080fd5b505184612631565b506001905550565b603754600160a81b900460ff1615610d85576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610ddd576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610deb8484612631565b50600190555050565b60415481565b6001600160a01b031660009081526033602052604090205460ff1690565b603a5481565b60345490565b6040602081905260009182529020546001600160a01b031681565b603754600160a81b900460ff1615610e8f576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610ee7576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610ef3611b51565b5060019055565b603754600160a01b900460ff1615610f4b576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b6000805160206134f983398151915280546002811415610fa3576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b60028255610ef36117ca565b6037546001600160a01b031681565b6000610fc8611663565b6001600160a01b0316336001600160a01b031614905090565b610fe9610fbe565b61103a576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61104381612be5565b806001600160a01b0316611055611663565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b600061070c612c09565b603754600160a81b900460ff1681565b603754600160a81b900460ff16156110f7576040805162461bcd60e51b815260206004820152600e60248201526d10d85c1a5d185b081c185d5cd95960921b604482015290519081900360640190fd5b6000805160206134f98339815191528054600281141561114f576040805162461bcd60e51b815260206004820152600e60248201526d1499595b9d1c985b9d0818d85b1b60921b604482015290519081900360640190fd5b600282558584146111a7576040805162461bcd60e51b815260206004820152601960248201527f506172616d65746572206c656e677468206d69736d6174636800000000000000604482015290519081900360640190fd5b60008060606111b582612c2a565b905060005b898110156113ee57603360008c8c848181106111d257fe5b602090810292909201356001600160a01b03168352508101919091526040016000205460ff16611242576040805162461bcd60e51b8152602060048201526016602482015275105cdcd95d081a5cc81b9bdd081cdd5c1c1bdc9d195960521b604482015290519081900360640190fd5b600089898381811061125057fe5b90506020020135116112a9576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b60005b6034548110156113e557603481815481106112c357fe5b6000918252602090912001546001600160a01b03168c8c848181106112e457fe5b905060200201356001600160a01b03166001600160a01b031614156113dd57600061132f6034838154811061131557fe5b6000918252602090912001546001600160a01b0316611688565b9050600084838151811061133f57fe5b60200260200101519050670de0b6b3a76400008111156113645750670de0b6b3a76400005b61139c61138f836012038e8e8881811061137a57fe5b9050602002013561174290919063ffffffff16565b889063ffffffff612d4016565b96506113d86113cb8284600a0a8f8f898181106113b557fe5b9050602002013561179c9092919063ffffffff16565b879063ffffffff612d4016565b955050505b6001016112ac565b506001016111ba565b50851561144a578582101561144a576040805162461bcd60e51b815260206004820152601e60248201527f4d696e7420616d6f756e74206c6f776572207468616e206d696e696d756d0000604482015290519081900360640190fd5b604080513381526020810184905281517f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d4121396885929181900390910190a1603b5483101580156114a15750603754600160a01b900460ff16155b156114ae576114ae6117ca565b603c54604080516340c10f1960e01b81523360048201526024810185905290516001600160a01b03909216916340c10f199160448082019260009290919082900301818387803b15801561150157600080fd5b505af1158015611515573d6000803e3d6000fd5b506000925050505b898110156115805760008b8b8381811061153357fe5b905060200201356001600160a01b0316905061157733308c8c8681811061155657fe5b90506020020135846001600160a01b0316611af1909392919063ffffffff16565b5060010161151d565b50603a54831061159257611592611b51565b5050506001825550505050505050565b6115aa610fbe565b6115fb576040805162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604482015290519081900360640190fd5b61160481612da1565b61163f5760405162461bcd60e51b81526004018080602001828103825260248152602001806135196024913960400191505060405180910390fd5b7fa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd955565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a5490565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b1580156116c457600080fd5b505afa1580156116d8573d6000803e3d6000fd5b505050506040513d60208110156116ee57600080fd5b505160ff16905060048110801590611707575060128111155b610be65760405162461bcd60e51b815260040180806020018281038252602981526020018061353d6029913960400191505060405180910390fd5b6000808260000b131561176d5761176683600084900b600a0a63ffffffff612ddd16565b9250611795565b60008260000b121561179557611792836000848103900b600a0a63ffffffff612e3616565b92505b5090919050565b6000806117af858563ffffffff612ddd16565b90506117c1818463ffffffff612e3616565b95945050505050565b603754600160a01b900460ff161561181b576040805162461bcd60e51b815260206004820152600f60248201526e149958985cda5b99c81c185d5cd959608a1b604482015290519081900360640190fd5b603c54604080516318160ddd60e01b815290516000926001600160a01b0316916318160ddd916004808301926020929190829003018186803b15801561186057600080fd5b505afa158015611874573d6000803e3d6000fd5b505050506040513d602081101561188a57600080fd5b50519050806118995750610bd9565b60006118a3612c09565b6042549091506001600160a01b031680158015906118c057508282115b15611a025760006118d7838563ffffffff612e7816565b905060006119026127106118f660435485612ddd90919063ffffffff16565b9063ffffffff612e3616565b90508082116119425760405162461bcd60e51b81526004018080602001828103825260228152602001806135876022913960400191505060405180910390fd5b80156119b657603c54604080516340c10f1960e01b81526001600160a01b03868116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b15801561199d57600080fd5b505af11580156119b1573d6000803e3d6000fd5b505050505b604080516001600160a01b03851681526020810184905280820183905290517f09516ecf4a8a86e59780a9befc6dee948bc9e60a36e3be68d31ea817ee8d2c809181900360600190a150505b603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b158015611a5057600080fd5b505afa158015611a64573d6000803e3d6000fd5b505050506040513d6020811015611a7a57600080fd5b5051925082821115611aec57603c54604080516339a7919f60e01b81526004810185905290516001600160a01b03909216916339a7919f9160248082019260009290919082900301818387803b158015611ad357600080fd5b505af1158015611ae7573d6000803e3d6000fd5b505050505b505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611b4b908590612eba565b50505050565b6000611b5b613072565b905080611b685750610bd9565b6000611b7261316f565b90506000611b86838363ffffffff612d4016565b9050600082611bb257603954611bab90670de0b6b3a76400009063ffffffff612e7816565b9050611bfe565b611bcb846118f684603954612ddd90919063ffffffff16565b905080670de0b6b3a76400001115611bf557611bab670de0b6b3a76400008263ffffffff612e7816565b50505050610bd9565b80611c0c5750505050610bd9565b60005b603454811015611d9b57600060348281548110611c2857fe5b6000918252602080832090910154604080516370a0823160e01b815230600482015290516001600160a01b03909216945084926370a0823192602480840193829003018186803b158015611c7b57600080fd5b505afa158015611c8f573d6000803e3d6000fd5b505050506040513d6020811015611ca557600080fd5b5051905080611cb5575050611d93565b6000611cc7828663ffffffff6131c116565b6001600160a01b03808516600090815260406020819052902054919250168015801590611cf45750600082115b15611d8e5780611d146001600160a01b038616828563ffffffff6131d616565b806001600160a01b03166347e7ef2486856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b158015611d7457600080fd5b505af1158015611d88573d6000803e3d6000fd5b50505050505b505050505b600101611c0f565b5060005b60365481101561206d57600060368281548110611db857fe5b60009182526020808320909101546040805163125f9e3360e01b815290516001600160a01b039092169450849263125f9e3392600480840193829003018186803b158015611e0557600080fd5b505afa158015611e19573d6000803e3d6000fd5b505050506040513d6020811015611e2f57600080fd5b505190506001600160a01b03811615612063576000826001600160a01b0316635653b4146040518163ffffffff1660e01b815260040160206040518083038186803b158015611e7d57600080fd5b505afa158015611e91573d6000803e3d6000fd5b505050506040513d6020811015611ea757600080fd5b5051905080611f3657306001600160a01b0316630e5c011e60368681548110611ecc57fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b158015611f1957600080fd5b505af1158015611f2d573d6000803e3d6000fd5b50505050612061565b60008290506000816001600160a01b03166370a0823160368881548110611f5957fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015611fa757600080fd5b505afa158015611fbb573d6000803e3d6000fd5b505050506040513d6020811015611fd157600080fd5b5051905082811061205e57306001600160a01b0316630e5c011e60368881548110611ff857fe5b6000918252602082200154604080516001600160e01b031960e086901b1681526001600160a01b039092166004830152516024808301939282900301818387803b15801561204557600080fd5b505af1158015612059573d6000803e3d6000fd5b505050505b50505b505b5050600101611d9f565b50604260009054906101000a90046001600160a01b03166001600160a01b0316638119c0656040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156120be57600080fd5b505af11580156120d2573d6000803e3d6000fd5b5050505050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db5490565b6001600160a01b03811661215c576040805162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f722069732061646472657373283029000000000000604482015290519081900360640190fd5b806001600160a01b031661216e611663565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36121ac81613228565b50565b604080516370a0823160e01b8152306004820152905160009183916001600160a01b038316916370a08231916024808301926020929190829003018186803b1580156121fa57600080fd5b505afa15801561220e573d6000803e3d6000fd5b505050506040513d602081101561222457600080fd5b5051915060005b6036548110156123695760006036828154811061224457fe5b600091825260209182902001546040805163551c457b60e11b81526001600160a01b0389811660048301529151919092169350839263aa388af69260248082019391829003018186803b15801561229a57600080fd5b505afa1580156122ae573d6000803e3d6000fd5b505050506040513d60208110156122c457600080fd5b5051156123605761235d816001600160a01b0316635f515226876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561232457600080fd5b505afa158015612338573d6000803e3d6000fd5b505050506040513d602081101561234e57600080fd5b5051859063ffffffff612d4016565b93505b5060010161222b565b5050919050565b606060008061237d610e1e565b9050606061238b6001612c2a565b90506060826040519080825280602002602001820160405280156123b9578160200160208202803883390190505b5090506060836040519080825280602002602001820160405280156123e8578160200160208202803883390190505b50905060008090508460405190808252806020026020018201604052801561241a578160200160208202803883390190505b50603854909750156124595760006124436127106118f66038548c612ddd90919063ffffffff16565b9050612455898263ffffffff612e7816565b9850505b60005b6034548110156125095760006124926034838154811061247857fe5b6000918252602090912001546001600160a01b03166121af565b905060006124a66034848154811061131557fe5b9050818684815181106124b557fe5b602002602001018181525050808584815181106124ce57fe5b60209081029190910101526124fd6124f083601284900363ffffffff61174216565b8a9063ffffffff612d4016565b9850505060010161245c565b5060005b6034548110156125ba57600085828151811061252557fe5b60200260200101519050670de0b6b3a764000081101561254a5750670de0b6b3a76400005b600061259c896118f68461259089888151811061256357fe5b60200260200101516012038b898151811061257a57fe5b602002602001015161174290919063ffffffff16565b9063ffffffff612ddd16565b90506125ae848263ffffffff612d4016565b9350505060010161250d565b5060006125cd898363ffffffff61324c16565b905060005b60345481101561262557612606886118f6848885815181106125f057fe5b6020026020010151612ddd90919063ffffffff16565b89828151811061261257fe5b60209081029190910101526001016125d2565b50505050505050915091565b60008211612686576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b6060600061269384612370565b915091506000603c60009054906101000a90046001600160a01b03166001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156126e757600080fd5b505afa1580156126fb573d6000803e3d6000fd5b505050506040513d602081101561271157600080fd5b5051604154909150156127ce576000612730828463ffffffff61324c16565b9050604154670de0b6b3a764000082116127615761275c670de0b6b3a76400008363ffffffff612e7816565b612779565b61277982670de0b6b3a764000063ffffffff612e7816565b11156127cc576040805162461bcd60e51b815260206004820152601e60248201527f4261636b696e6720737570706c79206c6971756964697479206572726f720000604482015290519081900360640190fd5b505b604080513381526020810187905281517f222838db2794d11532d940e8dec38ae307ed0b63cd97c233322e221f998767a6929181900390910190a160005b603454811015612a9d5783818151811061282257fe5b60200260200101516000141561283757612a95565b60006034828154811061284657fe5b60009182526020909120015485516001600160a01b03909116915085908390811061286d57fe5b6020026020010151816001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156128cb57600080fd5b505afa1580156128df573d6000803e3d6000fd5b505050506040513d60208110156128f557600080fd5b5051106129325761292d3386848151811061290c57fe5b6020026020010151836001600160a01b03166131d69092919063ffffffff16565b612a93565b6000604060006034858154811061294557fe5b60009182526020808320909101546001600160a01b0390811684529083019390935260409091019020541690508015612a52576000819050806001600160a01b031663d9caed12336034878154811061299a57fe5b9060005260206000200160009054906101000a90046001600160a01b03168a88815181106129c457fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015612a3457600080fd5b505af1158015612a48573d6000803e3d6000fd5b5050505050612a91565b6040805162461bcd60e51b815260206004820152600f60248201526e2634b8bab4b234ba3c9032b93937b960891b604482015290519081900360640190fd5b505b505b60010161280c565b508315612b4b576000805b8451811015612af3576000612ac36034838154811061131557fe5b9050612ae8612adb8260120388858151811061257a57fe5b849063ffffffff612d4016565b925050600101612aa8565b5084811015612b49576040805162461bcd60e51b815260206004820181905260248201527f52656465656d20616d6f756e74206c6f776572207468616e206d696e696d756d604482015290519081900360640190fd5b505b603c5460408051632770a7eb60e21b81523360048201526024810188905290516001600160a01b0390921691639dc29fac9160448082019260009290919082900301818387803b158015612b9e57600080fd5b505af1158015612bb2573d6000803e3d6000fd5b50505050603b5485118015612bd15750603754600160a01b900460ff16155b15612bde57612bde6117ca565b5050505050565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b600061070c612c1661316f565b612c1e613072565b9063ffffffff612d4016565b6060612c34610e1e565b604051908082528060200260200182016040528015612c5d578160200160208202803883390190505b506037549091506001600160a01b031660005b60345481101561236957612d21600a836001600160a01b031663aea9107860348581548110612c9b57fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b158015612ce957600080fd5b505afa158015612cfd573d6000803e3d6000fd5b505050506040513d6020811015612d1357600080fd5b50519063ffffffff61174216565b838281518110612d2d57fe5b6020908102919091010152600101612c70565b600082820183811015612d9a576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612dd557508115155b949350505050565b600082612dec57506000610be6565b82820282848281612df957fe5b0414612d9a5760405162461bcd60e51b81526004018080602001828103825260218152602001806135666021913960400191505060405180910390fd5b6000612d9a83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613279565b6000612d9a83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525061331b565b612ecc826001600160a01b0316612da1565b612f1d576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310612f5b5780518252601f199092019160209182019101612f3c565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612fbd576040519150601f19603f3d011682016040523d82523d6000602084013e612fc2565b606091505b509150915081613019576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611b4b5780806020019051602081101561303557600080fd5b5051611b4b5760405162461bcd60e51b815260040180806020018281038252602a8152602001806135a9602a913960400191505060405180910390fd5b6000805b60345481101561316b5760006034828154811061308f57fe5b6000918252602082200154603480546001600160a01b0390921693506130b9918590811061131557fe5b604080516370a0823160e01b815230600482015290519192506000916001600160a01b038516916370a08231916024808301926020929190829003018186803b15801561310557600080fd5b505afa158015613119573d6000803e3d6000fd5b505050506040513d602081101561312f57600080fd5b5051905080156131605761315d61315082601285900363ffffffff61174216565b869063ffffffff612d4016565b94505b505050600101613076565b5090565b6000805b60365481101561316b576131b76131aa6036838154811061319057fe5b6000918252602090912001546001600160a01b0316613375565b839063ffffffff612d4016565b9150600101613173565b6000612d9a8383670de0b6b3a764000061179c565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611aec908490612eba565b7f7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a55565b60008061326784670de0b6b3a764000063ffffffff612ddd16565b9050612dd5818463ffffffff612e3616565b600081836133055760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156132ca5781810151838201526020016132b2565b50505050905090810190601f1680156132f75780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161331157fe5b0495945050505050565b6000818484111561336d5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156132ca5781810151838201526020016132b2565b505050900390565b600081815b6034548110156123695760006133966034838154811061131557fe5b9050826001600160a01b031663aa388af6603484815481106133b457fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561340257600080fd5b505afa158015613416573d6000803e3d6000fd5b505050506040513d602081101561342c57600080fd5b5051156134ef576000836001600160a01b0316635f5152266034858154811061345157fe5b60009182526020918290200154604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301525160248083019392829003018186803b15801561349f57600080fd5b505afa1580156134b3573d6000803e3d6000fd5b505050506040513d60208110156134c957600080fd5b5051905080156134ed576134ea61315082601285900363ffffffff61174216565b94505b505b5060010161337a56fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45356e657720696d706c656d656e746174696f6e206973206e6f74206120636f6e7472616374546f6b656e206d75737420686176652073756666696369656e7420646563696d616c20706c61636573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77466565206d757374206e6f742062652067726561746572207468616e207969656c645361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565644f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f6d706c6574652074686520636c61696da265627a7a723158203f7824d3dfb9099003a39f9d314f7e755aeb69e5e84049357c6b4bf3ae75ec8964736f6c634300050b0032", "devdoc": { "methods": { "allocate()": { diff --git a/contracts/deployments/rinkeby/solcInputs/c2ea476b4aec8b6a8c5cdeb6adf2172f.json b/contracts/deployments/rinkeby/solcInputs/c2ea476b4aec8b6a8c5cdeb6adf2172f.json new file mode 100644 index 0000000000..afd7cd7d23 --- /dev/null +++ b/contracts/deployments/rinkeby/solcInputs/c2ea476b4aec8b6a8c5cdeb6adf2172f.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 poolCoinIndex = _getPoolCoinIndex(_asset);\n uint256 curveBalance = curvePool.balances(poolCoinIndex);\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 balances(uint256) external view returns (uint256);\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 if (_creditBalances[_account] == 0) {\n // Since there is no existing balance, we can directly set to\n // high resolution, and do not have to do any other bookkeeping\n nonRebasingCreditsPerToken[_account] = 1e27;\n } else {\n // Migrate an existing account:\n\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(\n _creditBalances[_account]\n );\n }\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 _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 // Calculate redemption outputs\n (\n uint256[] memory outputs,\n uint256 _backingValue\n ) = _calculateRedeemOutputs(_amount);\n\n // Check that OUSD is backed by enough assets\n uint256 _totalSupply = oUSD.totalSupply();\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 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 // 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 _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 (\n uint256[] memory outputs,\n uint256 totalValue\n ) = _calculateRedeemOutputs(_amount);\n return outputs;\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, uint256 totalBalance)\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 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 uint256[3] public balances;\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 balances[uint256(i)] = balances[i].add(uint256(_amounts[i]));\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 balances[uint256(_index)] = balances[uint256(_index)].sub(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 balances[uint256(i)] = balances[uint256(i)].sub(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\";\nimport \"../utils/Helpers.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 _checkBalance(address _asset)\n internal\n view\n returns (uint256 balance)\n {\n // Avoids rounding errors by returning the total value\n // in a single currency\n if (allAssets[0] == _asset) {\n uint256 decimals = Helpers.getDecimals(_asset);\n return storedTotalValue.scaleBy(int8(decimals - 18));\n } else {\n return 0;\n }\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 51f821608d..7387453d60 100644 --- a/contracts/hardhat.config.js +++ b/contracts/hardhat.config.js @@ -42,8 +42,9 @@ const { const MAINNET_DEPLOYER = "0x71F78361537A6f7B6818e7A760c8bC0146D93f50"; // Mainnet contracts are governed by the Governor contract (which derives off Timelock). -const MAINNET_GOVERNOR = "0x8e7bDFeCd1164C46ad51b58e49A611F954D23377"; -const MAINNET_MULTISIG = "0xe011fa2a6df98c69383457d87a056ed0103aa352"; +const MAINNET_GOVERNOR = "0x830622BDd79CC677eE6594E20bBda5B26568b781"; +// Multi-sig that controls the Governor. Aka "Guardian". +const MAINNET_MULTISIG = "0xbe2AB3d3d8F6a32b96414ebbd865dBD276d3d899"; const MAINNET_CLAIM_ADJUSTER = MAINNET_DEPLOYER; const MAINNET_STRATEGIST = "0xf14bbdf064e3f67f51cd9bd646ae3716ad938fdc"; diff --git a/contracts/storageLayout/mainnet/OUSD.json b/contracts/storageLayout/mainnet/OUSD.json index bb50d36685..8f8c0ddaa3 100644 --- a/contracts/storageLayout/mainnet/OUSD.json +++ b/contracts/storageLayout/mainnet/OUSD.json @@ -93,7 +93,7 @@ { "contract": "OUSD", "label": "rebaseState", - "type": "t_mapping(t_address,t_enum(RebaseOptions)12419)", + "type": "t_mapping(t_address,t_enum(RebaseOptions)14419)", "src": "contracts/token/OUSD.sol:50" } ], @@ -110,10 +110,10 @@ "t_mapping(t_address,t_uint256)": { "label": "mapping(address => uint256)" }, - "t_mapping(t_address,t_enum(RebaseOptions)12419)": { + "t_mapping(t_address,t_enum(RebaseOptions)14419)": { "label": "mapping(address => enum OUSD.RebaseOptions)" }, - "t_enum(RebaseOptions)12419": { + "t_enum(RebaseOptions)14419": { "label": "enum OUSD.RebaseOptions", "members": [ "NotSet", diff --git a/contracts/storageLayout/mainnet/VaultCore.json b/contracts/storageLayout/mainnet/VaultCore.json index c77e5c5b90..e1ed74e61b 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)18894_storage)", + "type": "t_mapping(t_address,t_struct(Asset)18980_storage)", "src": "contracts/vault/VaultStorage.sol:55" }, { @@ -33,7 +33,7 @@ { "contract": "VaultStorage", "label": "strategies", - "type": "t_mapping(t_address,t_struct(Strategy)18906_storage)", + "type": "t_mapping(t_address,t_struct(Strategy)18992_storage)", "src": "contracts/vault/VaultStorage.sol:63" }, { @@ -87,7 +87,7 @@ { "contract": "VaultStorage", "label": "oUSD", - "type": "t_contract(OUSD)15327", + "type": "t_contract(OUSD)15436", "src": "contracts/vault/VaultStorage.sol:80" }, { @@ -134,13 +134,13 @@ } ], "types": { - "t_mapping(t_address,t_struct(Asset)18894_storage)": { + "t_mapping(t_address,t_struct(Asset)18980_storage)": { "label": "mapping(address => struct VaultStorage.Asset)" }, "t_address": { "label": "address" }, - "t_struct(Asset)18894_storage": { + "t_struct(Asset)18980_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)18906_storage)": { + "t_mapping(t_address,t_struct(Strategy)18992_storage)": { "label": "mapping(address => struct VaultStorage.Strategy)" }, - "t_struct(Strategy)18906_storage": { + "t_struct(Strategy)18992_storage": { "label": "struct VaultStorage.Strategy", "members": [ { @@ -174,7 +174,7 @@ "t_uint256": { "label": "uint256" }, - "t_contract(OUSD)15327": { + "t_contract(OUSD)15436": { "label": "contract OUSD" }, "t_mapping(t_address,t_address)": { diff --git a/contracts/utils/addresses.js b/contracts/utils/addresses.js index f42cea3cb7..ff4fc6f00b 100644 --- a/contracts/utils/addresses.js +++ b/contracts/utils/addresses.js @@ -10,7 +10,7 @@ addresses.dead = "0x0000000000000000000000000000000000000001"; addresses.mainnet = {}; // Native stablecoins -addresses.mainnet.Binance = "0x3f5CE5FBFe3E9af3971dD833D26bA9b5C936f0bE"; +addresses.mainnet.Binance = "0xf977814e90da44bfa03b6295a0616a897441acec"; addresses.mainnet.DAI = "0x6b175474e89094c44da98b954eedeac495271d0f"; addresses.mainnet.USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"; addresses.mainnet.USDT = "0xdAC17F958D2ee523a2206206994597C13D831ec7"; diff --git a/contracts/utils/deploy.js b/contracts/utils/deploy.js index 646b8e774f..b2413750f8 100644 --- a/contracts/utils/deploy.js +++ b/contracts/utils/deploy.js @@ -10,6 +10,7 @@ const { isFork, isRinkeby, isMainnetOrRinkebyOrFork, + isSmokeTest, } = require("../test/helpers.js"); const { @@ -19,6 +20,7 @@ const { const addresses = require("../utils/addresses.js"); const { getTxOpts } = require("../utils/tx"); +const { proposeArgs } = require("../utils/governor"); // Wait for 3 blocks confirmation on Mainnet/Rinkeby. const NUM_CONFIRMATIONS = isMainnet || isRinkeby ? 3 : 0; @@ -275,9 +277,14 @@ function deploymentWithProposal(opts, fn) { } else { // Hardcoding gas estimate on Rinkeby since it fails for an undetermined reason... const gasLimit = isRinkeby ? 1000000 : null; - for (const proposal of proposals) { - const { contract, signature, args } = proposal; - log(`Sending goverance action ${signature} to ${address}`); + + const { governorAddr } = await getNamedAccounts(); + const sGovernor = await ethers.provider.getSigner(governorAddr); + + for (const action of proposal.actions) { + const { contract, signature, args } = action; + + log(`Sending governance action ${signature} to ${contract.address}`); await withConfirmation( contract .connect(sGovernor) diff --git a/dapp/network.mainnet.json b/dapp/network.mainnet.json index 8d0afee5c5..b89f83d07a 100644 --- a/dapp/network.mainnet.json +++ b/dapp/network.mainnet.json @@ -5786,7 +5786,7 @@ ] }, "OUSD": { - "address": "0x9d6975591E777D95Eef3bCC2a727846DA25d7083", + "address": "0x23DCc0Cc5F08b9D85daF8d29490c7f74a655b359", "abi": [ { "constant": true, @@ -11828,7 +11828,7 @@ ] }, "VaultCore": { - "address": "0xf00d4B19458C594d4Ea9D0B9861EDfD2c444fA9A", + "address": "0xA4D15507112c0DB37E1320Bf3Fff8891DFd1D2Ed", "abi": [ { "constant": true, diff --git a/dapp/network.rinkeby.json b/dapp/network.rinkeby.json index f1645ab4c8..74430d7782 100644 --- a/dapp/network.rinkeby.json +++ b/dapp/network.rinkeby.json @@ -14753,7 +14753,7 @@ ] }, "OUSD": { - "address": "0x1e4277abF53A0BD4dACC22Fc0Ab2FF9eb2192786", + "address": "0x06bFb84169EFd5aFafa39cBbf5018EE8624ef29b", "abi": [ { "constant": true, @@ -20810,7 +20810,7 @@ ] }, "VaultCore": { - "address": "0x24203812AcB90c75860db158c637C286259059ba", + "address": "0xe5Aeb6fa44234a0648373F6711498E5A2E27B51d", "abi": [ { "constant": true,