From ff1959d75e0c3af4ffd1b5d7d5125063984f99f1 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 23 Nov 2023 16:11:59 +0530 Subject: [PATCH] feat: add xvs vault sepolia deployments --- deployments/sepolia/XVSStore.json | 374 +++ deployments/sepolia/XVSVault.json | 2373 +++++++++++++++++ deployments/sepolia/XVSVaultProxy.json | 352 +++ .../b0e08c65414d4fb3a80b2146b3c121f2.json | 345 +++ 4 files changed, 3444 insertions(+) create mode 100644 deployments/sepolia/XVSStore.json create mode 100644 deployments/sepolia/XVSVault.json create mode 100644 deployments/sepolia/XVSVaultProxy.json create mode 100644 deployments/sepolia/solcInputs/b0e08c65414d4fb3a80b2146b3c121f2.json diff --git a/deployments/sepolia/XVSStore.json b/deployments/sepolia/XVSStore.json new file mode 100644 index 000000000..5da987a5c --- /dev/null +++ b/deployments/sepolia/XVSStore.json @@ -0,0 +1,374 @@ +{ + "address": "0xA3CF47ACf43B049aAf666DB67df3C4D80Ac0BfE3", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnerTransferred", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "acceptAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "emergencyRewardWithdraw", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokens", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "safeRewardTransfer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "setNewOwner", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_admin", + "type": "address" + } + ], + "name": "setPendingAdmin", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_tokenAddress", + "type": "address" + }, + { + "internalType": "bool", + "name": "status", + "type": "bool" + } + ], + "name": "setRewardToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xce7ece7c6bf005c894761735ce7dc5cc8203f2780712be02480e646064c16290", + "receipt": { + "to": null, + "from": "0x03862dFa5D0be8F64509C001cb8C6188194469DF", + "contractAddress": "0xA3CF47ACf43B049aAf666DB67df3C4D80Ac0BfE3", + "transactionIndex": 9, + "gasUsed": "634554", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xffe1ec5e86fcdd7954c981a00e03cbca9808fb3b37020daa7d080eaab50cb613", + "transactionHash": "0xce7ece7c6bf005c894761735ce7dc5cc8203f2780712be02480e646064c16290", + "logs": [], + "blockNumber": 4749650, + "cumulativeGasUsed": "823554", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "b0e08c65414d4fb3a80b2146b3c121f2", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPendingAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPendingAdmin\",\"type\":\"address\"}],\"name\":\"NewPendingAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnerTransferred\",\"type\":\"event\"},{\"constant\":false,\"inputs\":[],\"name\":\"acceptAdmin\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_tokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"emergencyRewardWithdraw\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokens\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"safeRewardTransfer\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"setNewOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_admin\",\"type\":\"address\"}],\"name\":\"setPendingAdmin\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_tokenAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"status\",\"type\":\"bool\"}],\"name\":\"setRewardToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"methods\":{\"emergencyRewardWithdraw(address,uint256)\":{\"params\":{\"_amount\":\"Amount of token to withdraw\",\"_tokenAddress\":\"Reward token address to withdraw\"}},\"safeRewardTransfer(address,address,uint256)\":{\"details\":\"Safe reward token transfer function, just in case if rounding error causes pool to not have enough tokens.\",\"params\":{\"_amount\":\"Amount to transfer\",\"_to\":\"Destination address of the reward\",\"token\":\"Reward token to transfer\"}},\"setNewOwner(address)\":{\"params\":{\"_owner\":\"The address of the owner to set Only callable admin\"}},\"setPendingAdmin(address)\":{\"params\":{\"_admin\":\"Propose an account as admin of the XVS store\"}},\"setRewardToken(address,bool)\":{\"params\":{\"_tokenAddress\":\"The address of a token to set as active or inactive\",\"status\":\"Set whether a reward token is active or not\"}}},\"title\":\"XVS Store\"},\"userdoc\":{\"methods\":{\"acceptAdmin()\":{\"notice\":\"Allows an account that is pending as admin to accept the role nly calllable by the pending admin\"},\"emergencyRewardWithdraw(address,uint256)\":{\"notice\":\"Security function to allow the owner of the contract to withdraw from the contract\"},\"safeRewardTransfer(address,address,uint256)\":{\"notice\":\"Safely transfer rewards. Only active reward tokens can be sent using this function. Only callable by owner\"},\"setNewOwner(address)\":{\"notice\":\"Set the contract owner\"},\"setPendingAdmin(address)\":{\"notice\":\"Allows the admin to propose a new admin Only callable admin\"},\"setRewardToken(address,bool)\":{\"notice\":\"Set or disable a reward token\"}},\"notice\":\"XVS Store responsible for distributing XVS rewards\"}},\"settings\":{\"compilationTarget\":{\"contracts/XVSVault/XVSStore.sol\":\"XVSStore\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"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 {\\n codehash := extcodehash(account)\\n }\\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 // solium-disable-next-line security/no-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\":\"0x3c2ef780599a2ae6913282b982633f07e405a4a9c8511590df571e2b773aef9d\"},\"contracts/Utils/IBEP20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the BEP20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {BEP20Detailed}.\\n */\\ninterface IBEP20 {\\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\":\"0x839b08895eb1ad83502d3631e8e9e3a856d2a8c63c46f070d604af7b26c62c07\"},\"contracts/Utils/SafeBEP20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./SafeMath.sol\\\";\\nimport \\\"./IBEP20.sol\\\";\\nimport \\\"./Address.sol\\\";\\n\\n/**\\n * @title SafeBEP20\\n * @dev Wrappers around BEP20 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 SafeBEP20 for BEP20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeBEP20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IBEP20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IBEP20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IBEP20 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(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeBEP20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IBEP20 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(IBEP20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(\\n value,\\n \\\"SafeBEP20: decreased allowance below zero\\\"\\n );\\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(IBEP20 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(), \\\"SafeBEP20: 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, \\\"SafeBEP20: low-level call failed\\\");\\n\\n if (returndata.length > 0) {\\n // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeBEP20: BEP20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x540ef6ddc47232a59d3ab0e95537f7a7d1c8a36f8dba315b010e60c6487bd768\"},\"contracts/Utils/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\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 return add(a, b, \\\"SafeMath: addition 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 function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, errorMessage);\\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 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 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 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\":\"0x9431fd772ed4abc038cdfe9ce6c0066897bd1685ad45848748d1952935d5b8ef\"},\"contracts/XVSVault/XVSStore.sol\":{\"content\":\"pragma solidity 0.5.16;\\nimport \\\"../Utils/SafeBEP20.sol\\\";\\nimport \\\"../Utils/IBEP20.sol\\\";\\n\\n/**\\n * @title XVS Store\\n * @author Venus\\n * @notice XVS Store responsible for distributing XVS rewards\\n */\\ncontract XVSStore {\\n using SafeMath for uint256;\\n using SafeBEP20 for IBEP20;\\n\\n /// @notice The Admin Address\\n address public admin;\\n\\n /// @notice The pending admin address\\n address public pendingAdmin;\\n\\n /// @notice The Owner Address\\n address public owner;\\n\\n /// @notice The reward tokens\\n mapping(address => bool) public rewardTokens;\\n\\n /// @notice Emitted when pendingAdmin is changed\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /// @notice Event emitted when admin changed\\n event AdminTransferred(address indexed oldAdmin, address indexed newAdmin);\\n\\n /// @notice Event emitted when owner changed\\n event OwnerTransferred(address indexed oldOwner, address indexed newOwner);\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n modifier onlyAdmin() {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n _;\\n }\\n\\n modifier onlyOwner() {\\n require(msg.sender == owner, \\\"only owner can\\\");\\n _;\\n }\\n\\n /**\\n * @notice Safely transfer rewards. Only active reward tokens can be sent using this function.\\n * Only callable by owner\\n * @dev Safe reward token transfer function, just in case if rounding error causes pool to not have enough tokens.\\n * @param token Reward token to transfer\\n * @param _to Destination address of the reward\\n * @param _amount Amount to transfer\\n */\\n function safeRewardTransfer(address token, address _to, uint256 _amount) external onlyOwner {\\n require(rewardTokens[token] == true, \\\"only reward token can\\\");\\n\\n if (address(token) != address(0)) {\\n uint256 tokenBalance = IBEP20(token).balanceOf(address(this));\\n if (_amount > tokenBalance) {\\n IBEP20(token).safeTransfer(_to, tokenBalance);\\n } else {\\n IBEP20(token).safeTransfer(_to, _amount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Allows the admin to propose a new admin\\n * Only callable admin\\n * @param _admin Propose an account as admin of the XVS store\\n */\\n function setPendingAdmin(address _admin) external onlyAdmin {\\n address oldPendingAdmin = pendingAdmin;\\n pendingAdmin = _admin;\\n emit NewPendingAdmin(oldPendingAdmin, _admin);\\n }\\n\\n /**\\n * @notice Allows an account that is pending as admin to accept the role\\n * nly calllable by the pending admin\\n */\\n function acceptAdmin() external {\\n require(msg.sender == pendingAdmin, \\\"only pending admin\\\");\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n admin = pendingAdmin;\\n pendingAdmin = address(0);\\n\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n emit AdminTransferred(oldAdmin, admin);\\n }\\n\\n /**\\n * @notice Set the contract owner\\n * @param _owner The address of the owner to set\\n * Only callable admin\\n */\\n function setNewOwner(address _owner) external onlyAdmin {\\n require(_owner != address(0), \\\"new owner is the zero address\\\");\\n address oldOwner = owner;\\n owner = _owner;\\n emit OwnerTransferred(oldOwner, _owner);\\n }\\n\\n /**\\n * @notice Set or disable a reward token\\n * @param _tokenAddress The address of a token to set as active or inactive\\n * @param status Set whether a reward token is active or not\\n */\\n function setRewardToken(address _tokenAddress, bool status) external {\\n require(msg.sender == admin || msg.sender == owner, \\\"only admin or owner can\\\");\\n rewardTokens[_tokenAddress] = status;\\n }\\n\\n /**\\n * @notice Security function to allow the owner of the contract to withdraw from the contract\\n * @param _tokenAddress Reward token address to withdraw\\n * @param _amount Amount of token to withdraw\\n */\\n function emergencyRewardWithdraw(address _tokenAddress, uint256 _amount) external onlyOwner {\\n IBEP20(_tokenAddress).safeTransfer(address(msg.sender), _amount);\\n }\\n}\\n\",\"keccak256\":\"0x8082f92b13448bd4fa982c93c763439f10fe016a5f3be6d613dfe3cca68501ef\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610a1b806100326000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80639ad99e68116100665780639ad99e681461012b578063f5a1f5b414610161578063f5ab16cc14610187578063f851a440146101c1578063fb66fb4d146101c95761009e565b80630e18b681146100a357806326782247146100ad5780634dd18bf5146100d1578063804e523e146100f75780638da5cb5b14610123575b600080fd5b6100ab6101f7565b005b6100b56102f3565b604080516001600160a01b039092168252519081900360200190f35b6100ab600480360360208110156100e757600080fd5b50356001600160a01b0316610302565b6100ab6004803603604081101561010d57600080fd5b506001600160a01b0381351690602001356103b5565b6100b5610423565b6100ab6004803603606081101561014157600080fd5b506001600160a01b03813581169160208101359091169060400135610432565b6100ab6004803603602081101561017757600080fd5b50356001600160a01b03166105bb565b6101ad6004803603602081101561019d57600080fd5b50356001600160a01b03166106b8565b604080519115158252519081900360200190f35b6100b56106cd565b6100ab600480360360408110156101df57600080fd5b506001600160a01b03813516906020013515156106dc565b6001546001600160a01b0316331461024b576040805162461bcd60e51b815260206004820152601260248201527137b7363c903832b73234b7339030b236b4b760711b604482015290519081900360640190fd5b60008054600180546001600160a01b038082166001600160a01b0319808616821787559092169092556040805182815260208101959095528051929093169390927fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a992918290030190a1600080546040516001600160a01b0391821692918516917ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec691a35050565b6001546001600160a01b031681565b6000546001600160a01b03163314610352576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a15050565b6002546001600160a01b03163314610405576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9037bbb732b91031b0b760911b604482015290519081900360640190fd5b61041f6001600160a01b038316338363ffffffff61077b16565b5050565b6002546001600160a01b031681565b6002546001600160a01b03163314610482576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9037bbb732b91031b0b760911b604482015290519081900360640190fd5b6001600160a01b03831660009081526003602052604090205460ff1615156001146104ec576040805162461bcd60e51b815260206004820152601560248201527437b7363c903932bbb0b932103a37b5b2b71031b0b760591b604482015290519081900360640190fd5b6001600160a01b038316156105b657604080516370a0823160e01b815230600482015290516000916001600160a01b038616916370a0823191602480820192602092909190829003018186803b15801561054557600080fd5b505afa158015610559573d6000803e3d6000fd5b505050506040513d602081101561056f57600080fd5b505190508082111561059a576105956001600160a01b038516848363ffffffff61077b16565b6105b4565b6105b46001600160a01b038516848463ffffffff61077b16565b505b505050565b6000546001600160a01b0316331461060b576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b604482015290519081900360640190fd5b6001600160a01b038116610666576040805162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f2061646472657373000000604482015290519081900360640190fd5b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8934ce4adea8d9ce0d714d2c22b86790e41b7731c84b926fbbdc1d40ff6533c990600090a35050565b60036020526000908152604090205460ff1681565b6000546001600160a01b031681565b6000546001600160a01b03163314806106ff57506002546001600160a01b031633145b610750576040805162461bcd60e51b815260206004820152601760248201527f6f6e6c792061646d696e206f72206f776e65722063616e000000000000000000604482015290519081900360640190fd5b6001600160a01b03919091166000908152600360205260409020805460ff1916911515919091179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526105b69084906107da826001600160a01b0316610980565b61082b576040805162461bcd60e51b815260206004820152601f60248201527f5361666542455032303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106108695780518252601f19909201916020918201910161084a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146108cb576040519150601f19603f3d011682016040523d82523d6000602084013e6108d0565b606091505b509150915081610927576040805162461bcd60e51b815260206004820181905260248201527f5361666542455032303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156105b45780806020019051602081101561094357600080fd5b50516105b45760405162461bcd60e51b815260040180806020018281038252602a8152602001806109bd602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906109b457508115155b94935050505056fe5361666542455032303a204245503230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a723158209e938a047cf0499058d9e6866f246e93c241e398b266c69ad7069ce461bc206364736f6c63430005100032", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061009e5760003560e01c80639ad99e68116100665780639ad99e681461012b578063f5a1f5b414610161578063f5ab16cc14610187578063f851a440146101c1578063fb66fb4d146101c95761009e565b80630e18b681146100a357806326782247146100ad5780634dd18bf5146100d1578063804e523e146100f75780638da5cb5b14610123575b600080fd5b6100ab6101f7565b005b6100b56102f3565b604080516001600160a01b039092168252519081900360200190f35b6100ab600480360360208110156100e757600080fd5b50356001600160a01b0316610302565b6100ab6004803603604081101561010d57600080fd5b506001600160a01b0381351690602001356103b5565b6100b5610423565b6100ab6004803603606081101561014157600080fd5b506001600160a01b03813581169160208101359091169060400135610432565b6100ab6004803603602081101561017757600080fd5b50356001600160a01b03166105bb565b6101ad6004803603602081101561019d57600080fd5b50356001600160a01b03166106b8565b604080519115158252519081900360200190f35b6100b56106cd565b6100ab600480360360408110156101df57600080fd5b506001600160a01b03813516906020013515156106dc565b6001546001600160a01b0316331461024b576040805162461bcd60e51b815260206004820152601260248201527137b7363c903832b73234b7339030b236b4b760711b604482015290519081900360640190fd5b60008054600180546001600160a01b038082166001600160a01b0319808616821787559092169092556040805182815260208101959095528051929093169390927fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a992918290030190a1600080546040516001600160a01b0391821692918516917ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec691a35050565b6001546001600160a01b031681565b6000546001600160a01b03163314610352576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b604482015290519081900360640190fd5b600180546001600160a01b038381166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a15050565b6002546001600160a01b03163314610405576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9037bbb732b91031b0b760911b604482015290519081900360640190fd5b61041f6001600160a01b038316338363ffffffff61077b16565b5050565b6002546001600160a01b031681565b6002546001600160a01b03163314610482576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9037bbb732b91031b0b760911b604482015290519081900360640190fd5b6001600160a01b03831660009081526003602052604090205460ff1615156001146104ec576040805162461bcd60e51b815260206004820152601560248201527437b7363c903932bbb0b932103a37b5b2b71031b0b760591b604482015290519081900360640190fd5b6001600160a01b038316156105b657604080516370a0823160e01b815230600482015290516000916001600160a01b038616916370a0823191602480820192602092909190829003018186803b15801561054557600080fd5b505afa158015610559573d6000803e3d6000fd5b505050506040513d602081101561056f57600080fd5b505190508082111561059a576105956001600160a01b038516848363ffffffff61077b16565b6105b4565b6105b46001600160a01b038516848463ffffffff61077b16565b505b505050565b6000546001600160a01b0316331461060b576040805162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b604482015290519081900360640190fd5b6001600160a01b038116610666576040805162461bcd60e51b815260206004820152601d60248201527f6e6577206f776e657220697320746865207a65726f2061646472657373000000604482015290519081900360640190fd5b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8934ce4adea8d9ce0d714d2c22b86790e41b7731c84b926fbbdc1d40ff6533c990600090a35050565b60036020526000908152604090205460ff1681565b6000546001600160a01b031681565b6000546001600160a01b03163314806106ff57506002546001600160a01b031633145b610750576040805162461bcd60e51b815260206004820152601760248201527f6f6e6c792061646d696e206f72206f776e65722063616e000000000000000000604482015290519081900360640190fd5b6001600160a01b03919091166000908152600360205260409020805460ff1916911515919091179055565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526105b69084906107da826001600160a01b0316610980565b61082b576040805162461bcd60e51b815260206004820152601f60248201527f5361666542455032303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106108695780518252601f19909201916020918201910161084a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d80600081146108cb576040519150601f19603f3d011682016040523d82523d6000602084013e6108d0565b606091505b509150915081610927576040805162461bcd60e51b815260206004820181905260248201527f5361666542455032303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156105b45780806020019051602081101561094357600080fd5b50516105b45760405162461bcd60e51b815260040180806020018281038252602a8152602001806109bd602a913960400191505060405180910390fd5b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906109b457508115155b94935050505056fe5361666542455032303a204245503230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a723158209e938a047cf0499058d9e6866f246e93c241e398b266c69ad7069ce461bc206364736f6c63430005100032", + "devdoc": { + "author": "Venus", + "methods": { + "emergencyRewardWithdraw(address,uint256)": { + "params": { + "_amount": "Amount of token to withdraw", + "_tokenAddress": "Reward token address to withdraw" + } + }, + "safeRewardTransfer(address,address,uint256)": { + "details": "Safe reward token transfer function, just in case if rounding error causes pool to not have enough tokens.", + "params": { + "_amount": "Amount to transfer", + "_to": "Destination address of the reward", + "token": "Reward token to transfer" + } + }, + "setNewOwner(address)": { + "params": { + "_owner": "The address of the owner to set Only callable admin" + } + }, + "setPendingAdmin(address)": { + "params": { + "_admin": "Propose an account as admin of the XVS store" + } + }, + "setRewardToken(address,bool)": { + "params": { + "_tokenAddress": "The address of a token to set as active or inactive", + "status": "Set whether a reward token is active or not" + } + } + }, + "title": "XVS Store" + }, + "userdoc": { + "methods": { + "acceptAdmin()": { + "notice": "Allows an account that is pending as admin to accept the role nly calllable by the pending admin" + }, + "emergencyRewardWithdraw(address,uint256)": { + "notice": "Security function to allow the owner of the contract to withdraw from the contract" + }, + "safeRewardTransfer(address,address,uint256)": { + "notice": "Safely transfer rewards. Only active reward tokens can be sent using this function. Only callable by owner" + }, + "setNewOwner(address)": { + "notice": "Set the contract owner" + }, + "setPendingAdmin(address)": { + "notice": "Allows the admin to propose a new admin Only callable admin" + }, + "setRewardToken(address,bool)": { + "notice": "Set or disable a reward token" + } + }, + "notice": "XVS Store responsible for distributing XVS rewards" + }, + "storageLayout": { + "storage": [ + { + "astId": 30028, + "contract": "contracts/XVSVault/XVSStore.sol:XVSStore", + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 30030, + "contract": "contracts/XVSVault/XVSStore.sol:XVSStore", + "label": "pendingAdmin", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 30032, + "contract": "contracts/XVSVault/XVSStore.sol:XVSStore", + "label": "owner", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 30036, + "contract": "contracts/XVSVault/XVSStore.sol:XVSStore", + "label": "rewardTokens", + "offset": 0, + "slot": "3", + "type": "t_mapping(t_address,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + } +} diff --git a/deployments/sepolia/XVSVault.json b/deployments/sepolia/XVSVault.json new file mode 100644 index 000000000..6cdae22fd --- /dev/null +++ b/deployments/sepolia/XVSVault.json @@ -0,0 +1,2373 @@ +{ + "address": "0x2ebddeb806956c6EA516574564fAf643176632CB", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "fromDelegate", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "toDelegate", + "type": "address" + } + ], + "name": "DelegateChangedV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBalance", + "type": "uint256" + } + ], + "name": "DelegateVotesChangedV2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ExecutedWithdrawal", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IPrime", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract IPrime", + "name": "newPrimeToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldPrimeRewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPrimeRewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldPrimePoolId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPrimePoolId", + "type": "uint256" + } + ], + "name": "NewPrimeToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "allocPoints", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardPerBlock", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lockPeriod", + "type": "uint256" + } + ], + "name": "PoolAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldAllocPoints", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newAllocPoints", + "type": "uint256" + } + ], + "name": "PoolUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RequestedWithdrawal", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldReward", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReward", + "type": "uint256" + } + ], + "name": "RewardAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldXvs", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "oldStore", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newXvs", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newStore", + "type": "address" + } + ], + "name": "StoreUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "userAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldOwedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newOwedAmount", + "type": "uint256" + } + ], + "name": "VaultDebtUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "admin", + "type": "address" + } + ], + "name": "VaultResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "pid", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldPeriod", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPeriod", + "type": "uint256" + } + ], + "name": "WithdrawalLockingPeriodUpdated", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "DELEGATION_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "DOMAIN_TYPEHASH", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "MAX_LOCK_PERIOD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract XVSVaultProxy", + "name": "xvsVaultProxy", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV5", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + }, + { + "internalType": "contract IBEP20", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardPerBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_lockPeriod", + "type": "uint256" + } + ], + "name": "add", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "name": "checkpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "fromBlock", + "type": "uint32" + }, + { + "internalType": "uint96", + "name": "votes", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_account", + "type": "address" + }, + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "claim", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + } + ], + "name": "delegate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "delegatee", + "type": "address" + }, + { + "internalType": "uint256", + "name": "nonce", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expiry", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "name": "delegateBySig", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegates", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "executeWithdrawal", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getCurrentVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getEligibleWithdrawalAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "withdrawalAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockNumber", + "type": "uint256" + } + ], + "name": "getPriorVotes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getRequestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getUserInfo", + "outputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "rewardDebt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "pendingWithdrawals", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "getWithdrawalRequests", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "lockedUntil", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "afterUpgrade", + "type": "uint128" + } + ], + "internalType": "struct XVSVaultStorageV1.WithdrawalRequest[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isStakedToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nonces", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "numCheckpoints", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "pause", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pendingRewardTransfers", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_user", + "type": "address" + } + ], + "name": "pendingWithdrawalsBeforeUpgrade", + "outputs": [ + { + "internalType": "uint256", + "name": "beforeUpgradeWithdrawalAmount", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingXVSVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "poolInfos", + "outputs": [ + { + "internalType": "contract IBEP20", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allocPoint", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastRewardBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "accRewardPerShare", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lockPeriod", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + } + ], + "name": "poolLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primePoolId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primeRewardToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "primeToken", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "requestWithdrawal", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "resume", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAmountsPerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_allocPoint", + "type": "uint256" + } + ], + "name": "set", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_primeToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_primeRewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_primePoolId", + "type": "uint256" + } + ], + "name": "setPrimeToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardAmount", + "type": "uint256" + } + ], + "name": "setRewardAmountPerBlock", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_newPeriod", + "type": "uint256" + } + ], + "name": "setWithdrawalLockingPeriod", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_xvs", + "type": "address" + }, + { + "internalType": "address", + "name": "_xvsStore", + "type": "address" + } + ], + "name": "setXvsStore", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalAllocPoints", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_pid", + "type": "uint256" + } + ], + "name": "updatePool", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaultPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "xvsStore", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x340ea3d4763b0cdfde62e79c8faaa4f07dde85262a021e0b05728fd4309d0737", + "receipt": { + "to": null, + "from": "0x03862dFa5D0be8F64509C001cb8C6188194469DF", + "contractAddress": "0x2ebddeb806956c6EA516574564fAf643176632CB", + "transactionIndex": 0, + "gasUsed": "4701756", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xb7a70f636b783a187610de9007c97f172fbd52d8a4d8266c4a0eec55c1f5a87c", + "transactionHash": "0x340ea3d4763b0cdfde62e79c8faaa4f07dde85262a021e0b05728fd4309d0737", + "logs": [], + "blockNumber": 4749647, + "cumulativeGasUsed": "4701756", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "b0e08c65414d4fb3a80b2146b3c121f2", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"fromDelegate\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"toDelegate\",\"type\":\"address\"}],\"name\":\"DelegateChangedV2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"DelegateVotesChangedV2\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ExecutedWithdrawal\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IPrime\",\"name\":\"oldPrimeToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"contract IPrime\",\"name\":\"newPrimeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPrimeRewardToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPrimeRewardToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldPrimePoolId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newPrimePoolId\",\"type\":\"uint256\"}],\"name\":\"NewPrimeToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"allocPoints\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewardPerBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lockPeriod\",\"type\":\"uint256\"}],\"name\":\"PoolAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldAllocPoints\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newAllocPoints\",\"type\":\"uint256\"}],\"name\":\"PoolUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"RequestedWithdrawal\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldReward\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newReward\",\"type\":\"uint256\"}],\"name\":\"RewardAmountUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldXvs\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldStore\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newXvs\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newStore\",\"type\":\"address\"}],\"name\":\"StoreUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"userAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldOwedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newOwedAmount\",\"type\":\"uint256\"}],\"name\":\"VaultDebtUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"VaultPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"VaultResumed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"pid\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldPeriod\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newPeriod\",\"type\":\"uint256\"}],\"name\":\"WithdrawalLockingPeriodUpdated\",\"type\":\"event\"},{\"constant\":true,\"inputs\":[],\"name\":\"DELEGATION_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"DOMAIN_TYPEHASH\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"MAX_LOCK_PERIOD\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract XVSVaultProxy\",\"name\":\"xvsVaultProxy\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV5\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_allocPoint\",\"type\":\"uint256\"},{\"internalType\":\"contract IBEP20\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_rewardPerBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_lockPeriod\",\"type\":\"uint256\"}],\"name\":\"add\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"checkpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"fromBlock\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"votes\",\"type\":\"uint96\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"}],\"name\":\"claim\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"}],\"name\":\"delegate\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegatee\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"name\":\"delegateBySig\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"delegates\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"}],\"name\":\"executeWithdrawal\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getCurrentVotes\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"getEligibleWithdrawalAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"withdrawalAmount\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"}],\"name\":\"getPriorVotes\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"getRequestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"getUserInfo\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"rewardDebt\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pendingWithdrawals\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"getWithdrawalRequests\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint128\",\"name\":\"lockedUntil\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"afterUpgrade\",\"type\":\"uint128\"}],\"internalType\":\"struct XVSVaultStorageV1.WithdrawalRequest[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isStakedToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"nonces\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"numCheckpoints\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"pendingReward\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"pendingRewardTransfers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_user\",\"type\":\"address\"}],\"name\":\"pendingWithdrawalsBeforeUpgrade\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"beforeUpgradeWithdrawalAmount\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingXVSVaultImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"poolInfos\",\"outputs\":[{\"internalType\":\"contract IBEP20\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"allocPoint\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lastRewardBlock\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"accRewardPerShare\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lockPeriod\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"}],\"name\":\"poolLength\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"primePoolId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"primeRewardToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"primeToken\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"requestWithdrawal\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"rewardTokenAmountsPerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_allocPoint\",\"type\":\"uint256\"}],\"name\":\"set\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"setAccessControl\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_primeToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_primeRewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_primePoolId\",\"type\":\"uint256\"}],\"name\":\"setPrimeToken\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_rewardAmount\",\"type\":\"uint256\"}],\"name\":\"setRewardAmountPerBlock\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_newPeriod\",\"type\":\"uint256\"}],\"name\":\"setWithdrawalLockingPeriod\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_xvs\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_xvsStore\",\"type\":\"address\"}],\"name\":\"setXvsStore\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"totalAllocPoints\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"_rewardToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_pid\",\"type\":\"uint256\"}],\"name\":\"updatePool\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"vaultPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"xvsAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"xvsStore\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"methods\":{\"add(address,uint256,address,uint256,uint256)\":{\"details\":\"This vault DOES NOT support deflationary tokens \\u2014 it expects that the amount of transferred tokens would equal the actually deposited amount. In practice this means that this vault DOES NOT support USDT and similar tokens (that do not provide these guarantees).\",\"params\":{\"_allocPoint\":\"Number of allocation points assigned to this pool\",\"_lockPeriod\":\"A period between withdrawal request and a moment when it's executable\",\"_rewardPerBlock\":\"Initial reward per block, in terms of _rewardToken\",\"_rewardToken\":\"Reward token address\",\"_token\":\"Staked token\"}},\"claim(address,address,uint256)\":{\"params\":{\"_account\":\"The account for which to claim rewards\",\"_pid\":\"The Pool Index\",\"_rewardToken\":\"The Reward Token Address\"}},\"delegate(address)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\"}},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"params\":{\"delegatee\":\"The address to delegate votes to\",\"expiry\":\"The time at which to expire the signature\",\"nonce\":\"The contract state required to match the signature\",\"r\":\"Half of the ECDSA signature pair\",\"s\":\"Half of the ECDSA signature pair\",\"v\":\"The recovery byte of the signature\"}},\"deposit(address,uint256,uint256)\":{\"params\":{\"_amount\":\"The amount to deposit to vault\",\"_pid\":\"The Pool Index\",\"_rewardToken\":\"The Reward Token Address\"}},\"executeWithdrawal(address,uint256)\":{\"params\":{\"_pid\":\"The Pool Index\",\"_rewardToken\":\"The Reward Token Address\"}},\"getCurrentVotes(address)\":{\"params\":{\"account\":\"The address to get votes balance\"},\"return\":\"The number of current votes for `account`\"},\"getEligibleWithdrawalAmount(address,uint256,address)\":{\"params\":{\"_pid\":\"The Pool Index\",\"_rewardToken\":\"The Reward Token Address\",\"_user\":\"The User Address\"},\"return\":\"withdrawalAmount Amount that the user can withdraw\"},\"getPriorVotes(address,uint256)\":{\"params\":{\"account\":\"The address of the account to check\",\"blockNumber\":\"The block number to get the vote balance at\"},\"return\":\"The balance that user staked\"},\"getRequestedAmount(address,uint256,address)\":{\"params\":{\"_pid\":\"The Pool Index\",\"_rewardToken\":\"The Reward Token Address\",\"_user\":\"The User Address\"},\"return\":\"Total amount of requested but not yet executed withdrawals (including both executable and locked ones)\"},\"getUserInfo(address,uint256,address)\":{\"params\":{\"_pid\":\"Pool index\",\"_rewardToken\":\"Reward token address\",\"_user\":\"User address\"},\"return\":\"amount Deposited amountrewardDebt Reward debt (technical value used to track past payouts)pendingWithdrawals Requested but not yet executed withdrawals\"},\"getWithdrawalRequests(address,uint256,address)\":{\"params\":{\"_pid\":\"The Pool Index\",\"_rewardToken\":\"The Reward Token Address\",\"_user\":\"The User Address\"},\"return\":\"An array of withdrawal requests\"},\"pendingReward(address,uint256,address)\":{\"params\":{\"_pid\":\"Pool index\",\"_rewardToken\":\"Reward token address\",\"_user\":\"User address\"},\"return\":\"Reward the user is eligible for in this pool, in terms of _rewardToken\"},\"pendingWithdrawalsBeforeUpgrade(address,uint256,address)\":{\"params\":{\"_pid\":\"The Pool Index\",\"_rewardToken\":\"The Reward Token Address\",\"_user\":\"The address of the user\"},\"return\":\"beforeUpgradeWithdrawalAmount Total pending withdrawal amount in requests made before the vault upgrade\"},\"poolLength(address)\":{\"params\":{\"rewardToken\":\"Reward token address\"},\"return\":\"Number of pools that distribute the specified token as a reward\"},\"requestWithdrawal(address,uint256,uint256)\":{\"params\":{\"_amount\":\"The amount to withdraw from the vault\",\"_pid\":\"The Pool Index\",\"_rewardToken\":\"The Reward Token Address\"}},\"set(address,uint256,uint256)\":{\"params\":{\"_allocPoint\":\"Number of allocation points assigned to this pool\",\"_pid\":\"Pool index\",\"_rewardToken\":\"Reward token address\"}},\"setAccessControl(address)\":{\"details\":\"Admin function to set the access control address\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"}},\"setPrimeToken(address,address,uint256)\":{\"params\":{\"_primePoolId\":\"pool id for reward\",\"_primeRewardToken\":\"address of reward token\",\"_primeToken\":\"address of the prime token contract\"}},\"setRewardAmountPerBlock(address,uint256)\":{\"params\":{\"_rewardAmount\":\"Number of allocation points assigned to this pool\",\"_rewardToken\":\"Reward token address\"}},\"setWithdrawalLockingPeriod(address,uint256,uint256)\":{\"params\":{\"_newPeriod\":\"New lock period\",\"_pid\":\"Pool index\",\"_rewardToken\":\"Reward token address\"}},\"updatePool(address,uint256)\":{\"params\":{\"_pid\":\"Pool index\",\"_rewardToken\":\"Reward token address\"}}},\"title\":\"XVS Vault\"},\"userdoc\":{\"methods\":{\"_become(address)\":{\"notice\":\"* Admin Functions **\"},\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"add(address,uint256,address,uint256,uint256)\":{\"notice\":\"Add a new token pool\"},\"claim(address,address,uint256)\":{\"notice\":\"Claim rewards for pool\"},\"delegate(address)\":{\"notice\":\"Delegate votes from `msg.sender` to `delegatee`\"},\"delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)\":{\"notice\":\"Delegates votes from signatory to `delegatee`\"},\"deposit(address,uint256,uint256)\":{\"notice\":\"Deposit XVSVault for XVS allocation\"},\"executeWithdrawal(address,uint256)\":{\"notice\":\"Execute withdrawal to XVSVault for XVS allocation\"},\"getCurrentVotes(address)\":{\"notice\":\"Gets the current votes balance for `account`\"},\"getEligibleWithdrawalAmount(address,uint256,address)\":{\"notice\":\"Get unlocked withdrawal amount\"},\"getPriorVotes(address,uint256)\":{\"notice\":\"Determine the xvs stake balance for an account\"},\"getRequestedAmount(address,uint256,address)\":{\"notice\":\"Get requested amount\"},\"getUserInfo(address,uint256,address)\":{\"notice\":\"Get user info with reward token address and pid\"},\"getWithdrawalRequests(address,uint256,address)\":{\"notice\":\"Returns the array of withdrawal requests that have not been executed yet\"},\"pause()\":{\"notice\":\"Pauses vault\"},\"pendingReward(address,uint256,address)\":{\"notice\":\"View function to see pending XVSs on frontend\"},\"pendingWithdrawalsBeforeUpgrade(address,uint256,address)\":{\"notice\":\"Gets the total pending withdrawal amount of a user before upgrade\"},\"poolLength(address)\":{\"notice\":\"Returns the number of pools with the specified reward token\"},\"requestWithdrawal(address,uint256,uint256)\":{\"notice\":\"Request withdrawal to XVSVault for XVS allocation\"},\"resume()\":{\"notice\":\"Resume vault\"},\"set(address,uint256,uint256)\":{\"notice\":\"Update the given pool's reward allocation point\"},\"setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"setPrimeToken(address,address,uint256)\":{\"notice\":\"Sets the address of the prime token contract\"},\"setRewardAmountPerBlock(address,uint256)\":{\"notice\":\"Update the given reward token's amount per block\"},\"setWithdrawalLockingPeriod(address,uint256,uint256)\":{\"notice\":\"Update the lock period after which a requested withdrawal can be executed\"},\"updatePool(address,uint256)\":{\"notice\":\"Update reward variables of the given pool to be up-to-date\"}},\"notice\":\"The XVS Vault allows XVS holders to lock their XVS to recieve voting rights in Venus governance and are rewarded with XVS.\"}},\"settings\":{\"compilationTarget\":{\"contracts/XVSVault/XVSVault.sol\":\"XVSVault\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.5.16;\\n\\nimport \\\"./IAccessControlManagerV5.sol\\\";\\n\\n/**\\n * @title AccessControlledV5\\n * @author Venus\\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.5.16)\\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\\n */\\ncontract AccessControlledV5 {\\n /// @notice Access control manager contract\\n IAccessControlManagerV5 private _accessControlManager;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[49] private __gap;\\n\\n /// @notice Emitted when access control manager contract address is changed\\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\\n\\n /**\\n * @notice Returns the address of the access control manager contract\\n */\\n function accessControlManager() external view returns (IAccessControlManagerV5) {\\n return _accessControlManager;\\n }\\n\\n /**\\n * @dev Internal function to set address of AccessControlManager\\n * @param accessControlManager_ The new address of the AccessControlManager\\n */\\n function _setAccessControlManager(address accessControlManager_) internal {\\n require(address(accessControlManager_) != address(0), \\\"invalid acess control manager address\\\");\\n address oldAccessControlManager = address(_accessControlManager);\\n _accessControlManager = IAccessControlManagerV5(accessControlManager_);\\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\\n }\\n\\n /**\\n * @notice Reverts if the call is not allowed by AccessControlManager\\n * @param signature Method signature\\n */\\n function _checkAccessAllowed(string memory signature) internal view {\\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\\n\\n if (!isAllowedToCall) {\\n revert(\\\"Unauthorized\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x4b724928650b944935bc91713782a8cf5bbd9cdb98b3e3fedf31e611c7e6df19\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV5.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.5.16;\\n\\n/**\\n * @title IAccessControlManagerV5\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV5` contract.\\n */\\ninterface IAccessControlManagerV5 {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n\\n /**\\n * @notice Gives a function call permission to one single account\\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\\n * \\t\\tMay emit a {RoleGranted} event.\\n * @param contractAddress address of contract for which call permissions will be granted\\n * @param functionSig signature e.g. \\\"functionName(uint,bool)\\\"\\n */\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n /**\\n * @notice Revokes an account's permission to a particular function call\\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\\n * \\t\\tMay emit a {RoleRevoked} event.\\n * @param contractAddress address of contract for which call permissions will be revoked\\n * @param functionSig signature e.g. \\\"functionName(uint,bool)\\\"\\n */\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n /**\\n * @notice Verifies if the given account can call a praticular contract's function\\n * @dev Since the contract is calling itself this function, we can get contracts address with msg.sender\\n * @param account address (eoa or contract) for which call permissions will be checked\\n * @param functionSig signature e.g. \\\"functionName(uint,bool)\\\"\\n * @return false if the user account cannot call the particular contract function\\n *\\n */\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x3563db4c75f7aa0b8a982bab591907dda192438a2368511b62a9c587a3e54226\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.5.16;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n}\\n\",\"keccak256\":\"0xa4f8ba3fbd95f83e1a056be73247f4c715904d94f47639d226746c2bc7b13484\"},\"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 {\\n codehash := extcodehash(account)\\n }\\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 // solium-disable-next-line security/no-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\":\"0x3c2ef780599a2ae6913282b982633f07e405a4a9c8511590df571e2b773aef9d\"},\"contracts/Utils/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// Adapted from OpenZeppelin Contracts v4.3.2 (utils/cryptography/ECDSA.sol)\\n\\n// SPDX-Copyright-Text: OpenZeppelin, 2021\\n// SPDX-Copyright-Text: Venus, 2021\\n\\npragma solidity ^0.5.16;\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\ncontract ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n } else if (error == RecoverError.InvalidSignatureV) {\\n revert(\\\"ECDSA: invalid signature 'v' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n if (v != 27 && v != 28) {\\n return (address(0), RecoverError.InvalidSignatureV);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n}\\n\",\"keccak256\":\"0xf27d7ad488b72c627370afa6e9acc520d4834a082363d1dc46b5573ac40a2d0a\"},\"contracts/Utils/IBEP20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the BEP20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {BEP20Detailed}.\\n */\\ninterface IBEP20 {\\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\":\"0x839b08895eb1ad83502d3631e8e9e3a856d2a8c63c46f070d604af7b26c62c07\"},\"contracts/Utils/SafeBEP20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\nimport \\\"./SafeMath.sol\\\";\\nimport \\\"./IBEP20.sol\\\";\\nimport \\\"./Address.sol\\\";\\n\\n/**\\n * @title SafeBEP20\\n * @dev Wrappers around BEP20 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 SafeBEP20 for BEP20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeBEP20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IBEP20 token, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IBEP20 token, address from, address to, uint256 value) internal {\\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n function safeApprove(IBEP20 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(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeBEP20: approve from non-zero to non-zero allowance\\\"\\n );\\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IBEP20 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(IBEP20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(\\n value,\\n \\\"SafeBEP20: decreased allowance below zero\\\"\\n );\\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(IBEP20 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(), \\\"SafeBEP20: 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, \\\"SafeBEP20: low-level call failed\\\");\\n\\n if (returndata.length > 0) {\\n // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeBEP20: BEP20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x540ef6ddc47232a59d3ab0e95537f7a7d1c8a36f8dba315b010e60c6487bd768\"},\"contracts/Utils/SafeCast.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an 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 *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value < 2 ** 128, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value < 2 ** 64, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value < 2 ** 32, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value < 2 ** 16, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits.\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value < 2 ** 8, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128) {\\n require(value >= -2 ** 127 && value < 2 ** 127, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return int128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64) {\\n require(value >= -2 ** 63 && value < 2 ** 63, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return int64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32) {\\n require(value >= -2 ** 31 && value < 2 ** 31, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return int32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16) {\\n require(value >= -2 ** 15 && value < 2 ** 15, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return int16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits.\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8) {\\n require(value >= -2 ** 7 && value < 2 ** 7, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return int8(value);\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n require(value < 2 ** 255, \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0xe6222292bd226980fd73c00eaf3a102c8638777aa3f9c7cd9b0d0fb621da0661\"},\"contracts/Utils/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\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 return add(a, b, \\\"SafeMath: addition 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 function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, errorMessage);\\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 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 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 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\":\"0x9431fd772ed4abc038cdfe9ce6c0066897bd1685ad45848748d1952935d5b8ef\"},\"contracts/XVSVault/XVSStore.sol\":{\"content\":\"pragma solidity 0.5.16;\\nimport \\\"../Utils/SafeBEP20.sol\\\";\\nimport \\\"../Utils/IBEP20.sol\\\";\\n\\n/**\\n * @title XVS Store\\n * @author Venus\\n * @notice XVS Store responsible for distributing XVS rewards\\n */\\ncontract XVSStore {\\n using SafeMath for uint256;\\n using SafeBEP20 for IBEP20;\\n\\n /// @notice The Admin Address\\n address public admin;\\n\\n /// @notice The pending admin address\\n address public pendingAdmin;\\n\\n /// @notice The Owner Address\\n address public owner;\\n\\n /// @notice The reward tokens\\n mapping(address => bool) public rewardTokens;\\n\\n /// @notice Emitted when pendingAdmin is changed\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /// @notice Event emitted when admin changed\\n event AdminTransferred(address indexed oldAdmin, address indexed newAdmin);\\n\\n /// @notice Event emitted when owner changed\\n event OwnerTransferred(address indexed oldOwner, address indexed newOwner);\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n modifier onlyAdmin() {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n _;\\n }\\n\\n modifier onlyOwner() {\\n require(msg.sender == owner, \\\"only owner can\\\");\\n _;\\n }\\n\\n /**\\n * @notice Safely transfer rewards. Only active reward tokens can be sent using this function.\\n * Only callable by owner\\n * @dev Safe reward token transfer function, just in case if rounding error causes pool to not have enough tokens.\\n * @param token Reward token to transfer\\n * @param _to Destination address of the reward\\n * @param _amount Amount to transfer\\n */\\n function safeRewardTransfer(address token, address _to, uint256 _amount) external onlyOwner {\\n require(rewardTokens[token] == true, \\\"only reward token can\\\");\\n\\n if (address(token) != address(0)) {\\n uint256 tokenBalance = IBEP20(token).balanceOf(address(this));\\n if (_amount > tokenBalance) {\\n IBEP20(token).safeTransfer(_to, tokenBalance);\\n } else {\\n IBEP20(token).safeTransfer(_to, _amount);\\n }\\n }\\n }\\n\\n /**\\n * @notice Allows the admin to propose a new admin\\n * Only callable admin\\n * @param _admin Propose an account as admin of the XVS store\\n */\\n function setPendingAdmin(address _admin) external onlyAdmin {\\n address oldPendingAdmin = pendingAdmin;\\n pendingAdmin = _admin;\\n emit NewPendingAdmin(oldPendingAdmin, _admin);\\n }\\n\\n /**\\n * @notice Allows an account that is pending as admin to accept the role\\n * nly calllable by the pending admin\\n */\\n function acceptAdmin() external {\\n require(msg.sender == pendingAdmin, \\\"only pending admin\\\");\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n admin = pendingAdmin;\\n pendingAdmin = address(0);\\n\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n emit AdminTransferred(oldAdmin, admin);\\n }\\n\\n /**\\n * @notice Set the contract owner\\n * @param _owner The address of the owner to set\\n * Only callable admin\\n */\\n function setNewOwner(address _owner) external onlyAdmin {\\n require(_owner != address(0), \\\"new owner is the zero address\\\");\\n address oldOwner = owner;\\n owner = _owner;\\n emit OwnerTransferred(oldOwner, _owner);\\n }\\n\\n /**\\n * @notice Set or disable a reward token\\n * @param _tokenAddress The address of a token to set as active or inactive\\n * @param status Set whether a reward token is active or not\\n */\\n function setRewardToken(address _tokenAddress, bool status) external {\\n require(msg.sender == admin || msg.sender == owner, \\\"only admin or owner can\\\");\\n rewardTokens[_tokenAddress] = status;\\n }\\n\\n /**\\n * @notice Security function to allow the owner of the contract to withdraw from the contract\\n * @param _tokenAddress Reward token address to withdraw\\n * @param _amount Amount of token to withdraw\\n */\\n function emergencyRewardWithdraw(address _tokenAddress, uint256 _amount) external onlyOwner {\\n IBEP20(_tokenAddress).safeTransfer(address(msg.sender), _amount);\\n }\\n}\\n\",\"keccak256\":\"0x8082f92b13448bd4fa982c93c763439f10fe016a5f3be6d613dfe3cca68501ef\"},\"contracts/XVSVault/XVSVault.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.5.16;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"../Utils/ECDSA.sol\\\";\\nimport \\\"../Utils/SafeBEP20.sol\\\";\\nimport \\\"../Utils/IBEP20.sol\\\";\\nimport \\\"./XVSVaultStorage.sol\\\";\\nimport \\\"./XVSVaultErrorReporter.sol\\\";\\nimport \\\"../Tokens/Prime/IPrime.sol\\\";\\nimport \\\"../Utils/SafeCast.sol\\\";\\nimport \\\"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol\\\";\\nimport { XVSStore } from \\\"./XVSStore.sol\\\";\\nimport { XVSVaultProxy } from \\\"./XVSVaultProxy.sol\\\";\\n\\n/**\\n * @title XVS Vault\\n * @author Venus\\n * @notice The XVS Vault allows XVS holders to lock their XVS to recieve voting rights in Venus governance and are rewarded with XVS.\\n */\\ncontract XVSVault is XVSVaultStorage, ECDSA, AccessControlledV5 {\\n using SafeMath for uint256;\\n using SafeCast for uint256;\\n using SafeBEP20 for IBEP20;\\n\\n /// @notice The upper bound for the lock period in a pool, 10 years\\n uint256 public constant MAX_LOCK_PERIOD = 60 * 60 * 24 * 365 * 10;\\n\\n /// @notice Event emitted when deposit\\n event Deposit(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\\n\\n /// @notice Event emitted when execute withrawal\\n event ExecutedWithdrawal(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\\n\\n /// @notice Event emitted when request withrawal\\n event RequestedWithdrawal(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\\n\\n /// @notice An event thats emitted when an account changes its delegate\\n event DelegateChangedV2(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\\n\\n /// @notice An event thats emitted when a delegate account's vote balance changes\\n event DelegateVotesChangedV2(address indexed delegate, uint previousBalance, uint newBalance);\\n\\n /// @notice An event emitted when the reward store address is updated\\n event StoreUpdated(address oldXvs, address oldStore, address newXvs, address newStore);\\n\\n /// @notice An event emitted when the withdrawal locking period is updated for a pool\\n event WithdrawalLockingPeriodUpdated(address indexed rewardToken, uint indexed pid, uint oldPeriod, uint newPeriod);\\n\\n /// @notice An event emitted when the reward amount per block is modified for a pool\\n event RewardAmountUpdated(address indexed rewardToken, uint oldReward, uint newReward);\\n\\n /// @notice An event emitted when a new pool is added\\n event PoolAdded(\\n address indexed rewardToken,\\n uint indexed pid,\\n address indexed token,\\n uint allocPoints,\\n uint rewardPerBlock,\\n uint lockPeriod\\n );\\n\\n /// @notice An event emitted when a pool allocation points are updated\\n event PoolUpdated(address indexed rewardToken, uint indexed pid, uint oldAllocPoints, uint newAllocPoints);\\n\\n /// @notice Event emitted when reward claimed\\n event Claim(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\\n\\n /// @notice Event emitted when vault is paused\\n event VaultPaused(address indexed admin);\\n\\n /// @notice Event emitted when vault is resumed after pause\\n event VaultResumed(address indexed admin);\\n\\n /// @notice Event emitted when protocol logs a debt to a user due to insufficient funds for pending reward distribution\\n event VaultDebtUpdated(\\n address indexed rewardToken,\\n address indexed userAddress,\\n uint256 oldOwedAmount,\\n uint256 newOwedAmount\\n );\\n\\n /// @notice Emitted when prime token contract address is changed\\n event NewPrimeToken(\\n IPrime indexed oldPrimeToken,\\n IPrime indexed newPrimeToken,\\n address oldPrimeRewardToken,\\n address newPrimeRewardToken,\\n uint256 oldPrimePoolId,\\n uint256 newPrimePoolId\\n );\\n\\n constructor() public {\\n admin = msg.sender;\\n }\\n\\n modifier onlyAdmin() {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n _;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @dev Prevents functions to execute when vault is paused.\\n */\\n modifier isActive() {\\n require(!vaultPaused, \\\"Vault is paused\\\");\\n _;\\n }\\n\\n /**\\n * @notice Pauses vault\\n */\\n function pause() external {\\n _checkAccessAllowed(\\\"pause()\\\");\\n require(!vaultPaused, \\\"Vault is already paused\\\");\\n vaultPaused = true;\\n emit VaultPaused(msg.sender);\\n }\\n\\n /**\\n * @notice Resume vault\\n */\\n function resume() external {\\n _checkAccessAllowed(\\\"resume()\\\");\\n require(vaultPaused, \\\"Vault is not paused\\\");\\n vaultPaused = false;\\n emit VaultResumed(msg.sender);\\n }\\n\\n /**\\n * @notice Returns the number of pools with the specified reward token\\n * @param rewardToken Reward token address\\n * @return Number of pools that distribute the specified token as a reward\\n */\\n function poolLength(address rewardToken) external view returns (uint256) {\\n return poolInfos[rewardToken].length;\\n }\\n\\n /**\\n * @notice Add a new token pool\\n * @dev This vault DOES NOT support deflationary tokens \\u2014 it expects that\\n * the amount of transferred tokens would equal the actually deposited\\n * amount. In practice this means that this vault DOES NOT support USDT\\n * and similar tokens (that do not provide these guarantees).\\n * @param _rewardToken Reward token address\\n * @param _allocPoint Number of allocation points assigned to this pool\\n * @param _token Staked token\\n * @param _rewardPerBlock Initial reward per block, in terms of _rewardToken\\n * @param _lockPeriod A period between withdrawal request and a moment when it's executable\\n */\\n function add(\\n address _rewardToken,\\n uint256 _allocPoint,\\n IBEP20 _token,\\n uint256 _rewardPerBlock,\\n uint256 _lockPeriod\\n ) external {\\n _checkAccessAllowed(\\\"add(address,uint256,address,uint256,uint256)\\\");\\n _ensureNonzeroAddress(_rewardToken);\\n _ensureNonzeroAddress(address(_token));\\n require(address(xvsStore) != address(0), \\\"Store contract address is empty\\\");\\n require(_allocPoint > 0, \\\"Alloc points must not be zero\\\");\\n\\n massUpdatePools(_rewardToken);\\n\\n PoolInfo[] storage poolInfo = poolInfos[_rewardToken];\\n\\n uint256 length = poolInfo.length;\\n for (uint256 pid = 0; pid < length; ++pid) {\\n require(poolInfo[pid].token != _token, \\\"Pool already added\\\");\\n }\\n\\n // We use balanceOf to get the supply amount, so shouldn't be possible to\\n // configure pools with different reward token but the same staked token\\n require(!isStakedToken[address(_token)], \\\"Token exists in other pool\\\");\\n\\n totalAllocPoints[_rewardToken] = totalAllocPoints[_rewardToken].add(_allocPoint);\\n\\n rewardTokenAmountsPerBlock[_rewardToken] = _rewardPerBlock;\\n\\n poolInfo.push(\\n PoolInfo({\\n token: _token,\\n allocPoint: _allocPoint,\\n lastRewardBlock: block.number,\\n accRewardPerShare: 0,\\n lockPeriod: _lockPeriod\\n })\\n );\\n isStakedToken[address(_token)] = true;\\n\\n XVSStore(xvsStore).setRewardToken(_rewardToken, true);\\n\\n emit PoolAdded(_rewardToken, poolInfo.length - 1, address(_token), _allocPoint, _rewardPerBlock, _lockPeriod);\\n }\\n\\n /**\\n * @notice Update the given pool's reward allocation point\\n * @param _rewardToken Reward token address\\n * @param _pid Pool index\\n * @param _allocPoint Number of allocation points assigned to this pool\\n */\\n function set(address _rewardToken, uint256 _pid, uint256 _allocPoint) external {\\n _checkAccessAllowed(\\\"set(address,uint256,uint256)\\\");\\n _ensureValidPool(_rewardToken, _pid);\\n\\n massUpdatePools(_rewardToken);\\n\\n PoolInfo[] storage poolInfo = poolInfos[_rewardToken];\\n uint256 newTotalAllocPoints = totalAllocPoints[_rewardToken].sub(poolInfo[_pid].allocPoint).add(_allocPoint);\\n require(newTotalAllocPoints > 0, \\\"Alloc points per reward token must not be zero\\\");\\n\\n uint256 oldAllocPoints = poolInfo[_pid].allocPoint;\\n poolInfo[_pid].allocPoint = _allocPoint;\\n totalAllocPoints[_rewardToken] = newTotalAllocPoints;\\n\\n emit PoolUpdated(_rewardToken, _pid, oldAllocPoints, _allocPoint);\\n }\\n\\n /**\\n * @notice Update the given reward token's amount per block\\n * @param _rewardToken Reward token address\\n * @param _rewardAmount Number of allocation points assigned to this pool\\n */\\n function setRewardAmountPerBlock(address _rewardToken, uint256 _rewardAmount) external {\\n _checkAccessAllowed(\\\"setRewardAmountPerBlock(address,uint256)\\\");\\n require(XVSStore(xvsStore).rewardTokens(_rewardToken), \\\"Invalid reward token\\\");\\n massUpdatePools(_rewardToken);\\n uint256 oldReward = rewardTokenAmountsPerBlock[_rewardToken];\\n rewardTokenAmountsPerBlock[_rewardToken] = _rewardAmount;\\n\\n emit RewardAmountUpdated(_rewardToken, oldReward, _rewardAmount);\\n }\\n\\n /**\\n * @notice Update the lock period after which a requested withdrawal can be executed\\n * @param _rewardToken Reward token address\\n * @param _pid Pool index\\n * @param _newPeriod New lock period\\n */\\n function setWithdrawalLockingPeriod(address _rewardToken, uint256 _pid, uint256 _newPeriod) external {\\n _checkAccessAllowed(\\\"setWithdrawalLockingPeriod(address,uint256,uint256)\\\");\\n _ensureValidPool(_rewardToken, _pid);\\n require(_newPeriod > 0 && _newPeriod < MAX_LOCK_PERIOD, \\\"Invalid new locking period\\\");\\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\\n uint256 oldPeriod = pool.lockPeriod;\\n pool.lockPeriod = _newPeriod;\\n\\n emit WithdrawalLockingPeriodUpdated(_rewardToken, _pid, oldPeriod, _newPeriod);\\n }\\n\\n /**\\n * @notice Deposit XVSVault for XVS allocation\\n * @param _rewardToken The Reward Token Address\\n * @param _pid The Pool Index\\n * @param _amount The amount to deposit to vault\\n */\\n function deposit(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant isActive {\\n _ensureValidPool(_rewardToken, _pid);\\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\\n UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\\n _updatePool(_rewardToken, _pid);\\n require(pendingWithdrawalsBeforeUpgrade(_rewardToken, _pid, msg.sender) == 0, \\\"execute pending withdrawal\\\");\\n\\n if (user.amount > 0) {\\n uint256 pending = _computeReward(user, pool);\\n if (pending > 0) {\\n _transferReward(_rewardToken, msg.sender, pending);\\n emit Claim(msg.sender, _rewardToken, _pid, pending);\\n }\\n }\\n pool.token.safeTransferFrom(msg.sender, address(this), _amount);\\n user.amount = user.amount.add(_amount);\\n user.rewardDebt = _cumulativeReward(user, pool);\\n\\n // Update Delegate Amount\\n if (address(pool.token) == xvsAddress) {\\n _moveDelegates(address(0), delegates[msg.sender], safe96(_amount, \\\"XVSVault::deposit: votes overflow\\\"));\\n }\\n\\n if (primeRewardToken == _rewardToken && _pid == primePoolId) {\\n primeToken.xvsUpdated(msg.sender);\\n }\\n\\n emit Deposit(msg.sender, _rewardToken, _pid, _amount);\\n }\\n\\n /**\\n * @notice Claim rewards for pool\\n * @param _account The account for which to claim rewards\\n * @param _rewardToken The Reward Token Address\\n * @param _pid The Pool Index\\n */\\n function claim(address _account, address _rewardToken, uint256 _pid) external nonReentrant isActive {\\n _ensureValidPool(_rewardToken, _pid);\\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\\n UserInfo storage user = userInfos[_rewardToken][_pid][_account];\\n _updatePool(_rewardToken, _pid);\\n require(pendingWithdrawalsBeforeUpgrade(_rewardToken, _pid, _account) == 0, \\\"execute pending withdrawal\\\");\\n\\n if (user.amount > 0) {\\n uint256 pending = _computeReward(user, pool);\\n\\n if (pending > 0) {\\n user.rewardDebt = _cumulativeReward(user, pool);\\n\\n _transferReward(_rewardToken, _account, pending);\\n emit Claim(_account, _rewardToken, _pid, pending);\\n }\\n }\\n }\\n\\n /**\\n * @notice Pushes withdrawal request to the requests array and updates\\n * the pending withdrawals amount. The requests are always sorted\\n * by unlock time (descending) so that the earliest to execute requests\\n * are always at the end of the array.\\n * @param _user The user struct storage pointer\\n * @param _requests The user's requests array storage pointer\\n * @param _amount The amount being requested\\n */\\n function pushWithdrawalRequest(\\n UserInfo storage _user,\\n WithdrawalRequest[] storage _requests,\\n uint _amount,\\n uint _lockedUntil\\n ) internal {\\n uint i = _requests.length;\\n _requests.push(WithdrawalRequest(0, 0, 1));\\n // Keep it sorted so that the first to get unlocked request is always at the end\\n for (; i > 0 && _requests[i - 1].lockedUntil <= _lockedUntil; --i) {\\n _requests[i] = _requests[i - 1];\\n }\\n _requests[i] = WithdrawalRequest(_amount, _lockedUntil.toUint128(), 1);\\n _user.pendingWithdrawals = _user.pendingWithdrawals.add(_amount);\\n }\\n\\n /**\\n * @notice Pops the requests with unlock time < now from the requests\\n * array and deducts the computed amount from the user's pending\\n * withdrawals counter. Assumes that the requests array is sorted\\n * by unclock time (descending).\\n * @dev This function **removes** the eligible requests from the requests\\n * array. If this function is called, the withdrawal should actually\\n * happen (or the transaction should be reverted).\\n * @param _user The user struct storage pointer\\n * @param _requests The user's requests array storage pointer\\n * @return beforeUpgradeWithdrawalAmount The amount eligible for withdrawal before upgrade (this amount should be\\n * sent to the user, otherwise the state would be inconsistent).\\n * @return afterUpgradeWithdrawalAmount The amount eligible for withdrawal after upgrade (this amount should be\\n * sent to the user, otherwise the state would be inconsistent).\\n */\\n function popEligibleWithdrawalRequests(\\n UserInfo storage _user,\\n WithdrawalRequest[] storage _requests\\n ) internal returns (uint beforeUpgradeWithdrawalAmount, uint afterUpgradeWithdrawalAmount) {\\n // Since the requests are sorted by their unlock time, we can just\\n // pop them from the array and stop at the first not-yet-eligible one\\n for (uint i = _requests.length; i > 0 && isUnlocked(_requests[i - 1]); --i) {\\n if (_requests[i - 1].afterUpgrade == 1) {\\n afterUpgradeWithdrawalAmount = afterUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\\n } else {\\n beforeUpgradeWithdrawalAmount = beforeUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\\n }\\n\\n _requests.pop();\\n }\\n _user.pendingWithdrawals = _user.pendingWithdrawals.sub(\\n afterUpgradeWithdrawalAmount.add(beforeUpgradeWithdrawalAmount)\\n );\\n return (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount);\\n }\\n\\n /**\\n * @notice Checks if the request is eligible for withdrawal.\\n * @param _request The request struct storage pointer\\n * @return True if the request is eligible for withdrawal, false otherwise\\n */\\n function isUnlocked(WithdrawalRequest storage _request) private view returns (bool) {\\n return _request.lockedUntil <= block.timestamp;\\n }\\n\\n /**\\n * @notice Execute withdrawal to XVSVault for XVS allocation\\n * @param _rewardToken The Reward Token Address\\n * @param _pid The Pool Index\\n */\\n function executeWithdrawal(address _rewardToken, uint256 _pid) external nonReentrant isActive {\\n _ensureValidPool(_rewardToken, _pid);\\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\\n UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];\\n\\n uint256 beforeUpgradeWithdrawalAmount;\\n uint256 afterUpgradeWithdrawalAmount;\\n\\n (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount) = popEligibleWithdrawalRequests(user, requests);\\n require(beforeUpgradeWithdrawalAmount > 0 || afterUpgradeWithdrawalAmount > 0, \\\"nothing to withdraw\\\");\\n\\n // Having both old-style and new-style requests is not allowed and shouldn't be possible\\n require(beforeUpgradeWithdrawalAmount == 0 || afterUpgradeWithdrawalAmount == 0, \\\"inconsistent state\\\");\\n\\n if (beforeUpgradeWithdrawalAmount > 0) {\\n _updatePool(_rewardToken, _pid);\\n uint256 pending = user.amount.mul(pool.accRewardPerShare).div(1e12).sub(user.rewardDebt);\\n XVSStore(xvsStore).safeRewardTransfer(_rewardToken, msg.sender, pending);\\n user.amount = user.amount.sub(beforeUpgradeWithdrawalAmount);\\n user.rewardDebt = user.amount.mul(pool.accRewardPerShare).div(1e12);\\n pool.token.safeTransfer(address(msg.sender), beforeUpgradeWithdrawalAmount);\\n } else {\\n user.amount = user.amount.sub(afterUpgradeWithdrawalAmount);\\n totalPendingWithdrawals[_rewardToken][_pid] = totalPendingWithdrawals[_rewardToken][_pid].sub(\\n afterUpgradeWithdrawalAmount\\n );\\n pool.token.safeTransfer(address(msg.sender), afterUpgradeWithdrawalAmount);\\n }\\n\\n emit ExecutedWithdrawal(\\n msg.sender,\\n _rewardToken,\\n _pid,\\n beforeUpgradeWithdrawalAmount.add(afterUpgradeWithdrawalAmount)\\n );\\n }\\n\\n /**\\n * @notice Returns before and after upgrade pending withdrawal amount\\n * @param _requests The user's requests array storage pointer\\n * @return beforeUpgradeWithdrawalAmount The amount eligible for withdrawal before upgrade\\n * @return afterUpgradeWithdrawalAmount The amount eligible for withdrawal after upgrade\\n */\\n function getRequestedWithdrawalAmount(\\n WithdrawalRequest[] storage _requests\\n ) internal view returns (uint beforeUpgradeWithdrawalAmount, uint afterUpgradeWithdrawalAmount) {\\n for (uint i = _requests.length; i > 0; --i) {\\n if (_requests[i - 1].afterUpgrade == 1) {\\n afterUpgradeWithdrawalAmount = afterUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\\n } else {\\n beforeUpgradeWithdrawalAmount = beforeUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\\n }\\n }\\n return (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount);\\n }\\n\\n /**\\n * @notice Request withdrawal to XVSVault for XVS allocation\\n * @param _rewardToken The Reward Token Address\\n * @param _pid The Pool Index\\n * @param _amount The amount to withdraw from the vault\\n */\\n function requestWithdrawal(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant isActive {\\n _ensureValidPool(_rewardToken, _pid);\\n require(_amount > 0, \\\"requested amount cannot be zero\\\");\\n UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\\n require(user.amount >= user.pendingWithdrawals.add(_amount), \\\"requested amount is invalid\\\");\\n\\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];\\n\\n uint beforeUpgradeWithdrawalAmount;\\n\\n (beforeUpgradeWithdrawalAmount, ) = getRequestedWithdrawalAmount(requests);\\n require(beforeUpgradeWithdrawalAmount == 0, \\\"execute pending withdrawal\\\");\\n\\n _updatePool(_rewardToken, _pid);\\n uint256 pending = _computeReward(user, pool);\\n _transferReward(_rewardToken, msg.sender, pending);\\n\\n uint lockedUntil = pool.lockPeriod.add(block.timestamp);\\n\\n pushWithdrawalRequest(user, requests, _amount, lockedUntil);\\n totalPendingWithdrawals[_rewardToken][_pid] = totalPendingWithdrawals[_rewardToken][_pid].add(_amount);\\n user.rewardDebt = _cumulativeReward(user, pool);\\n\\n // Update Delegate Amount\\n if (address(pool.token) == xvsAddress) {\\n _moveDelegates(\\n delegates[msg.sender],\\n address(0),\\n safe96(_amount, \\\"XVSVault::requestWithdrawal: votes overflow\\\")\\n );\\n }\\n\\n if (primeRewardToken == _rewardToken && _pid == primePoolId) {\\n primeToken.xvsUpdated(msg.sender);\\n }\\n\\n emit Claim(msg.sender, _rewardToken, _pid, pending);\\n emit RequestedWithdrawal(msg.sender, _rewardToken, _pid, _amount);\\n }\\n\\n /**\\n * @notice Get unlocked withdrawal amount\\n * @param _rewardToken The Reward Token Address\\n * @param _pid The Pool Index\\n * @param _user The User Address\\n * @return withdrawalAmount Amount that the user can withdraw\\n */\\n function getEligibleWithdrawalAmount(\\n address _rewardToken,\\n uint256 _pid,\\n address _user\\n ) external view returns (uint withdrawalAmount) {\\n _ensureValidPool(_rewardToken, _pid);\\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\\n // Since the requests are sorted by their unlock time, we can take\\n // the entries from the end of the array and stop at the first\\n // not-yet-eligible one\\n for (uint i = requests.length; i > 0 && isUnlocked(requests[i - 1]); --i) {\\n withdrawalAmount = withdrawalAmount.add(requests[i - 1].amount);\\n }\\n return withdrawalAmount;\\n }\\n\\n /**\\n * @notice Get requested amount\\n * @param _rewardToken The Reward Token Address\\n * @param _pid The Pool Index\\n * @param _user The User Address\\n * @return Total amount of requested but not yet executed withdrawals (including both executable and locked ones)\\n */\\n function getRequestedAmount(address _rewardToken, uint256 _pid, address _user) external view returns (uint256) {\\n _ensureValidPool(_rewardToken, _pid);\\n UserInfo storage user = userInfos[_rewardToken][_pid][_user];\\n return user.pendingWithdrawals;\\n }\\n\\n /**\\n * @notice Returns the array of withdrawal requests that have not been executed yet\\n * @param _rewardToken The Reward Token Address\\n * @param _pid The Pool Index\\n * @param _user The User Address\\n * @return An array of withdrawal requests\\n */\\n function getWithdrawalRequests(\\n address _rewardToken,\\n uint256 _pid,\\n address _user\\n ) external view returns (WithdrawalRequest[] memory) {\\n _ensureValidPool(_rewardToken, _pid);\\n return withdrawalRequests[_rewardToken][_pid][_user];\\n }\\n\\n /**\\n * @notice View function to see pending XVSs on frontend\\n * @param _rewardToken Reward token address\\n * @param _pid Pool index\\n * @param _user User address\\n * @return Reward the user is eligible for in this pool, in terms of _rewardToken\\n */\\n function pendingReward(address _rewardToken, uint256 _pid, address _user) external view returns (uint256) {\\n _ensureValidPool(_rewardToken, _pid);\\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\\n UserInfo storage user = userInfos[_rewardToken][_pid][_user];\\n uint256 accRewardPerShare = pool.accRewardPerShare;\\n uint256 supply = pool.token.balanceOf(address(this)).sub(totalPendingWithdrawals[_rewardToken][_pid]);\\n uint256 curBlockNumber = block.number;\\n uint256 rewardTokenPerBlock = rewardTokenAmountsPerBlock[_rewardToken];\\n if (curBlockNumber > pool.lastRewardBlock && supply != 0) {\\n uint256 multiplier = curBlockNumber.sub(pool.lastRewardBlock);\\n uint256 reward = multiplier.mul(rewardTokenPerBlock).mul(pool.allocPoint).div(\\n totalAllocPoints[_rewardToken]\\n );\\n accRewardPerShare = accRewardPerShare.add(reward.mul(1e12).div(supply));\\n }\\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\\n (, uint256 afterUpgradeWithdrawalAmount) = getRequestedWithdrawalAmount(requests);\\n return user.amount.sub(afterUpgradeWithdrawalAmount).mul(accRewardPerShare).div(1e12).sub(user.rewardDebt);\\n }\\n\\n // Update reward variables for all pools. Be careful of gas spending!\\n function massUpdatePools(address _rewardToken) internal {\\n uint256 length = poolInfos[_rewardToken].length;\\n for (uint256 pid = 0; pid < length; ++pid) {\\n _updatePool(_rewardToken, pid);\\n }\\n }\\n\\n /**\\n * @notice Update reward variables of the given pool to be up-to-date\\n * @param _rewardToken Reward token address\\n * @param _pid Pool index\\n */\\n function updatePool(address _rewardToken, uint256 _pid) external isActive {\\n _ensureValidPool(_rewardToken, _pid);\\n _updatePool(_rewardToken, _pid);\\n }\\n\\n // Update reward variables of the given pool to be up-to-date.\\n function _updatePool(address _rewardToken, uint256 _pid) internal {\\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\\n if (block.number <= pool.lastRewardBlock) {\\n return;\\n }\\n uint256 supply = pool.token.balanceOf(address(this));\\n supply = supply.sub(totalPendingWithdrawals[_rewardToken][_pid]);\\n if (supply == 0) {\\n pool.lastRewardBlock = block.number;\\n return;\\n }\\n uint256 curBlockNumber = block.number;\\n uint256 multiplier = curBlockNumber.sub(pool.lastRewardBlock);\\n uint256 reward = multiplier.mul(rewardTokenAmountsPerBlock[_rewardToken]).mul(pool.allocPoint).div(\\n totalAllocPoints[_rewardToken]\\n );\\n pool.accRewardPerShare = pool.accRewardPerShare.add(reward.mul(1e12).div(supply));\\n pool.lastRewardBlock = block.number;\\n }\\n\\n function _ensureValidPool(address rewardToken, uint256 pid) internal view {\\n require(pid < poolInfos[rewardToken].length, \\\"vault: pool exists?\\\");\\n }\\n\\n /**\\n * @notice Get user info with reward token address and pid\\n * @param _rewardToken Reward token address\\n * @param _pid Pool index\\n * @param _user User address\\n * @return amount Deposited amount\\n * @return rewardDebt Reward debt (technical value used to track past payouts)\\n * @return pendingWithdrawals Requested but not yet executed withdrawals\\n */\\n function getUserInfo(\\n address _rewardToken,\\n uint256 _pid,\\n address _user\\n ) external view returns (uint256 amount, uint256 rewardDebt, uint256 pendingWithdrawals) {\\n _ensureValidPool(_rewardToken, _pid);\\n UserInfo storage user = userInfos[_rewardToken][_pid][_user];\\n amount = user.amount;\\n rewardDebt = user.rewardDebt;\\n pendingWithdrawals = user.pendingWithdrawals;\\n }\\n\\n /**\\n * @notice Gets the total pending withdrawal amount of a user before upgrade\\n * @param _rewardToken The Reward Token Address\\n * @param _pid The Pool Index\\n * @param _user The address of the user\\n * @return beforeUpgradeWithdrawalAmount Total pending withdrawal amount in requests made before the vault upgrade\\n */\\n function pendingWithdrawalsBeforeUpgrade(\\n address _rewardToken,\\n uint256 _pid,\\n address _user\\n ) public view returns (uint256 beforeUpgradeWithdrawalAmount) {\\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\\n (beforeUpgradeWithdrawalAmount, ) = getRequestedWithdrawalAmount(requests);\\n return beforeUpgradeWithdrawalAmount;\\n }\\n\\n /**\\n * @notice Get the XVS stake balance of an account (excluding the pending withdrawals)\\n * @param account The address of the account to check\\n * @return The balance that user staked\\n */\\n function getStakeAmount(address account) internal view returns (uint96) {\\n require(xvsAddress != address(0), \\\"XVSVault::getStakeAmount: xvs address is not set\\\");\\n\\n PoolInfo[] storage poolInfo = poolInfos[xvsAddress];\\n\\n uint256 length = poolInfo.length;\\n for (uint256 pid = 0; pid < length; ++pid) {\\n if (address(poolInfo[pid].token) == address(xvsAddress)) {\\n UserInfo storage user = userInfos[xvsAddress][pid][account];\\n return safe96(user.amount.sub(user.pendingWithdrawals), \\\"XVSVault::getStakeAmount: votes overflow\\\");\\n }\\n }\\n return uint96(0);\\n }\\n\\n /**\\n * @notice Delegate votes from `msg.sender` to `delegatee`\\n * @param delegatee The address to delegate votes to\\n */\\n function delegate(address delegatee) external isActive {\\n return _delegate(msg.sender, delegatee);\\n }\\n\\n /**\\n * @notice Delegates votes from signatory to `delegatee`\\n * @param delegatee The address to delegate votes to\\n * @param nonce The contract state required to match the signature\\n * @param expiry The time at which to expire the signature\\n * @param v The recovery byte of the signature\\n * @param r Half of the ECDSA signature pair\\n * @param s Half of the ECDSA signature pair\\n */\\n function delegateBySig(\\n address delegatee,\\n uint nonce,\\n uint expiry,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external isActive {\\n bytes32 domainSeparator = keccak256(\\n abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(\\\"XVSVault\\\")), getChainId(), address(this))\\n );\\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\\n bytes32 digest = keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n address signatory = ECDSA.recover(digest, v, r, s);\\n require(nonce == nonces[signatory]++, \\\"XVSVault::delegateBySig: invalid nonce\\\");\\n require(block.timestamp <= expiry, \\\"XVSVault::delegateBySig: signature expired\\\");\\n return _delegate(signatory, delegatee);\\n }\\n\\n /**\\n * @notice Gets the current votes balance for `account`\\n * @param account The address to get votes balance\\n * @return The number of current votes for `account`\\n */\\n function getCurrentVotes(address account) external view returns (uint96) {\\n uint32 nCheckpoints = numCheckpoints[account];\\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\\n }\\n\\n function _delegate(address delegator, address delegatee) internal {\\n address currentDelegate = delegates[delegator];\\n uint96 delegatorBalance = getStakeAmount(delegator);\\n delegates[delegator] = delegatee;\\n\\n emit DelegateChangedV2(delegator, currentDelegate, delegatee);\\n\\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\\n }\\n\\n function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {\\n if (srcRep != dstRep && amount > 0) {\\n if (srcRep != address(0)) {\\n uint32 srcRepNum = numCheckpoints[srcRep];\\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\\n uint96 srcRepNew = sub96(srcRepOld, amount, \\\"XVSVault::_moveVotes: vote amount underflows\\\");\\n _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\\n }\\n\\n if (dstRep != address(0)) {\\n uint32 dstRepNum = numCheckpoints[dstRep];\\n uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\\n uint96 dstRepNew = add96(dstRepOld, amount, \\\"XVSVault::_moveVotes: vote amount overflows\\\");\\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\\n }\\n }\\n }\\n\\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\\n uint32 blockNumber = safe32(block.number, \\\"XVSVault::_writeCheckpoint: block number exceeds 32 bits\\\");\\n\\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\\n } else {\\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\\n numCheckpoints[delegatee] = nCheckpoints + 1;\\n }\\n\\n emit DelegateVotesChangedV2(delegatee, oldVotes, newVotes);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\\n require(n < 2 ** 96, errorMessage);\\n return uint96(n);\\n }\\n\\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n uint96 c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function getChainId() internal pure returns (uint) {\\n uint256 chainId;\\n assembly {\\n chainId := chainid()\\n }\\n return chainId;\\n }\\n\\n /**\\n * @notice Determine the xvs stake balance for an account\\n * @param account The address of the account to check\\n * @param blockNumber The block number to get the vote balance at\\n * @return The balance that user staked\\n */\\n function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96) {\\n require(blockNumber < block.number, \\\"XVSVault::getPriorVotes: not yet determined\\\");\\n\\n uint32 nCheckpoints = numCheckpoints[account];\\n if (nCheckpoints == 0) {\\n return 0;\\n }\\n\\n // First check most recent balance\\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\\n return checkpoints[account][nCheckpoints - 1].votes;\\n }\\n\\n // Next check implicit zero balance\\n if (checkpoints[account][0].fromBlock > blockNumber) {\\n return 0;\\n }\\n\\n uint32 lower = 0;\\n uint32 upper = nCheckpoints - 1;\\n while (upper > lower) {\\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\\n Checkpoint memory cp = checkpoints[account][center];\\n if (cp.fromBlock == blockNumber) {\\n return cp.votes;\\n } else if (cp.fromBlock < blockNumber) {\\n lower = center;\\n } else {\\n upper = center - 1;\\n }\\n }\\n return checkpoints[account][lower].votes;\\n }\\n\\n /*** Admin Functions ***/\\n\\n function _become(XVSVaultProxy xvsVaultProxy) external {\\n require(msg.sender == xvsVaultProxy.admin(), \\\"only proxy admin can change brains\\\");\\n require(xvsVaultProxy._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n function setXvsStore(address _xvs, address _xvsStore) external onlyAdmin {\\n _ensureNonzeroAddress(_xvs);\\n _ensureNonzeroAddress(_xvsStore);\\n\\n address oldXvsContract = xvsAddress;\\n address oldStore = xvsStore;\\n require(oldXvsContract == address(0), \\\"already initialized\\\");\\n\\n xvsAddress = _xvs;\\n xvsStore = _xvsStore;\\n\\n _notEntered = true;\\n\\n emit StoreUpdated(oldXvsContract, oldStore, _xvs, _xvsStore);\\n }\\n\\n /**\\n * @notice Sets the address of the prime token contract\\n * @param _primeToken address of the prime token contract\\n * @param _primeRewardToken address of reward token\\n * @param _primePoolId pool id for reward\\n */\\n function setPrimeToken(IPrime _primeToken, address _primeRewardToken, uint256 _primePoolId) external onlyAdmin {\\n require(address(_primeToken) != address(0), \\\"prime token cannot be zero address\\\");\\n require(_primeRewardToken != address(0), \\\"reward cannot be zero address\\\");\\n\\n _ensureValidPool(_primeRewardToken, _primePoolId);\\n\\n emit NewPrimeToken(primeToken, _primeToken, primeRewardToken, _primeRewardToken, primePoolId, _primePoolId);\\n\\n primeToken = _primeToken;\\n primeRewardToken = _primeRewardToken;\\n primePoolId = _primePoolId;\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlAddress New address for the access control\\n */\\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\\n _setAccessControlManager(newAccessControlAddress);\\n }\\n\\n /**\\n * @dev Reverts if the provided address is a zero address\\n * @param address_ Address to check\\n */\\n function _ensureNonzeroAddress(address address_) internal pure {\\n require(address_ != address(0), \\\"zero address not allowed\\\");\\n }\\n\\n /**\\n * @dev Transfers the reward to the user, taking into account the rewards store\\n * balance and the previous debt. If there are not enough rewards in the store,\\n * transfers the available funds and records the debt amount in pendingRewardTransfers.\\n * @param rewardToken Reward token address\\n * @param userAddress User address\\n * @param amount Reward amount, in reward tokens\\n */\\n function _transferReward(address rewardToken, address userAddress, uint256 amount) internal {\\n address xvsStore_ = xvsStore;\\n uint256 storeBalance = IBEP20(rewardToken).balanceOf(xvsStore_);\\n uint256 debtDueToFailedTransfers = pendingRewardTransfers[rewardToken][userAddress];\\n uint256 fullAmount = amount.add(debtDueToFailedTransfers);\\n\\n if (fullAmount <= storeBalance) {\\n if (debtDueToFailedTransfers != 0) {\\n pendingRewardTransfers[rewardToken][userAddress] = 0;\\n emit VaultDebtUpdated(rewardToken, userAddress, debtDueToFailedTransfers, 0);\\n }\\n XVSStore(xvsStore_).safeRewardTransfer(rewardToken, userAddress, fullAmount);\\n return;\\n }\\n // Overflow isn't possible due to the check above\\n uint256 newOwedAmount = fullAmount - storeBalance;\\n pendingRewardTransfers[rewardToken][userAddress] = newOwedAmount;\\n emit VaultDebtUpdated(rewardToken, userAddress, debtDueToFailedTransfers, newOwedAmount);\\n XVSStore(xvsStore_).safeRewardTransfer(rewardToken, userAddress, storeBalance);\\n }\\n\\n /**\\n * @dev Computes cumulative reward for all user's shares\\n * @param user UserInfo storage struct\\n * @param pool PoolInfo storage struct\\n */\\n function _cumulativeReward(UserInfo storage user, PoolInfo storage pool) internal view returns (uint256) {\\n return user.amount.sub(user.pendingWithdrawals).mul(pool.accRewardPerShare).div(1e12);\\n }\\n\\n /**\\n * @dev Computes the reward for all user's shares\\n * @param user UserInfo storage struct\\n * @param pool PoolInfo storage struct\\n */\\n function _computeReward(UserInfo storage user, PoolInfo storage pool) internal view returns (uint256) {\\n return _cumulativeReward(user, pool).sub(user.rewardDebt);\\n }\\n}\\n\",\"keccak256\":\"0xdd9ab5b2392ef97f571c57b7dea203ade0598bd5609ee9bce7b9f8c01f42805f\"},\"contracts/XVSVault/XVSVaultErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract XVSVaultErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0xa79877a281d024f0d03dbf1842a36a972ee6c1aa36ba93e3d646726d40684a26\"},\"contracts/XVSVault/XVSVaultProxy.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./XVSVaultStorage.sol\\\";\\nimport \\\"./XVSVaultErrorReporter.sol\\\";\\n\\n/**\\n * @title XVS Vault Proxy\\n * @author Venus\\n * @notice XVS Vault Proxy contract\\n */\\ncontract XVSVaultProxy is XVSVaultAdminStorage, XVSVaultErrorReporter {\\n /**\\n * @notice Emitted when pendingXVSVaultImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingXVSVaultImplementation is accepted, which means XVS Vault implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingXVSVaultImplementation;\\n\\n pendingXVSVaultImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation\\n if (msg.sender != pendingXVSVaultImplementation) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = implementation;\\n address oldPendingImplementation = pendingXVSVaultImplementation;\\n\\n implementation = pendingXVSVaultImplementation;\\n\\n pendingXVSVaultImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, implementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n function() external payable {\\n // delegate all other functions to current implementation\\n (bool success, ) = implementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize)\\n }\\n default {\\n return(free_mem_ptr, returndatasize)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb39af917833659fe38f2f76924deda420babed8259b27741dc6cb402ade4d124\"},\"contracts/XVSVault/XVSVaultStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"../Utils/SafeMath.sol\\\";\\nimport \\\"../Utils/IBEP20.sol\\\";\\nimport \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract XVSVaultAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of XVS Vault\\n */\\n address public implementation;\\n\\n /**\\n * @notice Pending brains of XVS Vault\\n */\\n address public pendingXVSVaultImplementation;\\n}\\n\\ncontract XVSVaultStorageV1 is XVSVaultAdminStorage {\\n /// @notice Guard variable for re-entrancy checks\\n bool internal _notEntered;\\n\\n /// @notice The reward token store\\n address public xvsStore;\\n\\n /// @notice The xvs token address\\n address public xvsAddress;\\n\\n // Reward tokens created per block indentified by reward token address.\\n mapping(address => uint256) public rewardTokenAmountsPerBlock;\\n\\n /// @notice Info of each user.\\n struct UserInfo {\\n uint256 amount;\\n uint256 rewardDebt;\\n uint256 pendingWithdrawals;\\n }\\n\\n // Info of each pool.\\n struct PoolInfo {\\n IBEP20 token; // Address of token contract to stake.\\n uint256 allocPoint; // How many allocation points assigned to this pool.\\n uint256 lastRewardBlock; // Last block number that reward tokens distribution occurs.\\n uint256 accRewardPerShare; // Accumulated per share, times 1e12. See below.\\n uint256 lockPeriod; // Min time between withdrawal request and its execution.\\n }\\n\\n // Infomation about a withdrawal request\\n struct WithdrawalRequest {\\n uint256 amount;\\n uint128 lockedUntil;\\n uint128 afterUpgrade;\\n }\\n\\n // Info of each user that stakes tokens.\\n mapping(address => mapping(uint256 => mapping(address => UserInfo))) internal userInfos;\\n\\n // Info of each pool.\\n mapping(address => PoolInfo[]) public poolInfos;\\n\\n // Total allocation points. Must be the sum of all allocation points in all pools.\\n mapping(address => uint256) public totalAllocPoints;\\n\\n // Info of requested but not yet executed withdrawals\\n mapping(address => mapping(uint256 => mapping(address => WithdrawalRequest[]))) internal withdrawalRequests;\\n\\n /// @notice DEPRECATED A record of each accounts delegate (before the voting power fix)\\n mapping(address => address) private __oldDelegatesSlot;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice DEPRECATED A record of votes checkpoints for each account, by index (before the voting power fix)\\n mapping(address => mapping(uint32 => Checkpoint)) private __oldCheckpointsSlot;\\n\\n /// @notice DEPRECATED The number of checkpoints for each account (before the voting power fix)\\n mapping(address => uint32) private __oldNumCheckpointsSlot;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH =\\n keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH =\\n keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n}\\n\\ncontract XVSVaultStorage is XVSVaultStorageV1 {\\n /// @notice A record of each accounts delegate\\n mapping(address => address) public delegates;\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice Tracks pending withdrawals for all users for a particular reward token and pool id\\n mapping(address => mapping(uint256 => uint256)) internal totalPendingWithdrawals;\\n\\n /// @notice pause indicator for Vault\\n bool public vaultPaused;\\n\\n /// @notice if the token is added to any of the pools\\n mapping(address => bool) public isStakedToken;\\n\\n /// @notice Amount we owe to users because of failed transfer attempts\\n mapping(address => mapping(address => uint256)) public pendingRewardTransfers;\\n\\n /// @notice Prime token contract address\\n IPrime public primeToken;\\n\\n /// @notice Reward token for which prime token is issued for staking\\n address public primeRewardToken;\\n\\n /// @notice Pool ID for which prime token is issued for staking\\n uint256 public primePoolId;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\",\"keccak256\":\"0x6389c160d86eab54ce1a8a5138c39f38d858381b7d8881d146cd937feab3dac9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a01b031916331790556153a6806100326000396000f3fe608060405234801561001057600080fd5b50600436106102bb5760003560e01c80638456cb5911610182578063c2102596116100e9578063e7a324dc116100a2578063f55401621161007c578063f55401621461061c578063f851a44014610624578063fba1b1f91461062c578063fe5a451a1461063f576102bb565b8063e7a324dc146105eb578063e8f2be6f146105f3578063f1127ed8146105fb576102bb565b8063c210259614610577578063c3c754a814610597578063c3cda520146105aa578063d7ae45e2146105bd578063dae66bbe146105d0578063de0368b2146105e3576102bb565b80639e2b6c4d1161013b5780639e2b6c4d1461050e578063a09eab7a14610521578063a9d69a6914610534578063add8933714610547578063b4a0bdf31461054f578063b4b5ea5714610564576102bb565b80638456cb59146104875780638ed7333d1461048f57806392e35000146104a257806393c7c4d1146104c657806398e1b31b146104d9578063996cba68146104fb576102bb565b80634298bdbd116102265780636fcfff45116101df5780636fcfff45146103f957806373d025d614610419578063782d6fe11461042e5780637ac924561461044e5780637ecebe00146104615780638308d7e914610474576102bb565b80634298bdbd14610392578063587cde1e146103a55780635c19a95c146103b85780635c60da1b146103cb5780635ff56315146103d35780636dd77cbd146103e6576102bb565b806320606b701161027857806320606b701461033f57806324f52bbf14610347578063267822471461035c5780632eda5c6c14610364578063358ae036146103775780633d4180f91461037f576102bb565b8063046f7da2146102c05780630af13728146102ca5780630efe6a8b146102f3578063115b512f1461030657806319129e5a146103195780631d504dc61461032c575b600080fd5b6102c8610647565b005b6102dd6102d8366004613de7565b6106d2565b6040516102ea9190614d0d565b60405180910390f35b6102c8610301366004613e9f565b610718565b6102c8610314366004613e9f565b610a0d565b6102c8610327366004613cf4565b610dc1565b6102c861033a366004613fc7565b610df7565b6102dd610f28565b61034f610f3f565b6040516102ea9190614bab565b61034f610f4e565b6102dd610372366004613cf4565b610f5d565b61034f610f6f565b6102dd61038d366004613d30565b610f7e565b6102dd6103a0366004613cf4565b610f9b565b61034f6103b3366004613cf4565b610fad565b6102c86103c6366004613cf4565b610fc8565b61034f610ff5565b6102c86103e1366004613d30565b611004565b6102dd6103f4366004613de7565b6110f8565b61040c610407366004613cf4565b6111ad565b6040516102ea919061508b565b6104216111c5565b6040516102ea9190614cff565b61044161043c366004613db7565b6111ce565b6040516102ea91906150b4565b6102c861045c366004613db7565b6113dd565b6102dd61046f366004613cf4565b611726565b6102c8610482366004613e9f565b611738565b6102c86118de565b6102c861049d366004613db7565b611963565b6104b56104b0366004613db7565b61199e565b6040516102ea959493929190614d7a565b6102c86104d4366004613db7565b6119f3565b6104ec6104e7366004613de7565b611b19565b6040516102ea93929190615070565b6102c8610509366004613d6a565b611b6b565b6102c861051c366004613e9f565b611cfd565b6102dd61052f366004613de7565b611de8565b6102dd610542366004613de7565b61202d565b61034f61206f565b61055761207e565b6040516102ea9190614d6c565b610441610572366004613cf4565b61208d565b61058a610585366004613de7565b612100565b6040516102ea9190614cee565b6104216105a5366004613cf4565b6121ba565b6102c86105b8366004613ed1565b6121cf565b6102dd6105cb366004613cf4565b612373565b6102c86105de366004613fa6565b61238e565b61034f61249a565b6102dd6124a9565b6102dd6124b5565b61060e610609366004613f58565b6124bb565b6040516102ea929190615099565b6102dd6124f0565b61034f6124f8565b6102c861063a366004613e2a565b612507565b6105576127d3565b61067060405180604001604052806008815260200167726573756d65282960c01b8152506127e2565b60135460ff1661069b5760405162461bcd60e51b815260040161069290614e37565b60405180910390fd5b6013805460ff1916905560405133907fd2619572a1464e0df0bb351d834fd47f3350984d7bfdb1ab69cfcb0b8e42141590600090a2565b60006106de8484612884565b506001600160a01b0380841660009081526007602090815260408083208684528252808320938516835292905220600201545b9392505050565b600354600160a01b900460ff166107415760405162461bcd60e51b815260040161069290614f87565b6003805460ff60a01b1916905560135460ff16156107715760405162461bcd60e51b815260040161069290614e27565b61077b8383612884565b6001600160a01b038316600090815260086020526040812080548490811061079f57fe5b600091825260208083206001600160a01b038816845260078252604080852088865283528085203386529092529220600590910290910191506107e285856128bb565b6107ed85853361202d565b1561080a5760405162461bcd60e51b815260040161069290614f37565b80541561087f57600061081d8284612a76565b9050801561087d57610830863383612a8a565b84866001600160a01b0316336001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645846040516108749190614d0d565b60405180910390a45b505b815461089c906001600160a01b031633308663ffffffff612d0316565b80546108ae908463ffffffff612d6416565b81556108ba8183612da6565b600182015560055482546001600160a01b039081169116141561092157336000908152600f6020908152604080832054815160608101909252602180835261092194936001600160a01b039092169261091c9289929061525890830139612dd4565b612e03565b6017546001600160a01b03868116911614801561093f575060185484145b156109a7576016546040516337f23cd360e01b81526001600160a01b03909116906337f23cd390610974903390600401614bb9565b600060405180830381600087803b15801561098e57600080fd5b505af11580156109a2573d6000803e3d6000fd5b505050505b83856001600160a01b0316336001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7866040516109eb9190614d0d565b60405180910390a450506003805460ff60a01b1916600160a01b179055505050565b600354600160a01b900460ff16610a365760405162461bcd60e51b815260040161069290614f87565b6003805460ff60a01b1916905560135460ff1615610a665760405162461bcd60e51b815260040161069290614e27565b610a708383612884565b60008111610a905760405162461bcd60e51b815260040161069290614f57565b6001600160a01b0383166000908152600760209081526040808320858452825280832033845290915290206002810154610ad0908363ffffffff612d6416565b81541015610af05760405162461bcd60e51b815260040161069290615017565b6001600160a01b0384166000908152600860205260408120805485908110610b1457fe5b600091825260208083206001600160a01b0389168452600a825260408085208986528352808520338652909252908320600590920201925090610b5682612f95565b5090508015610b775760405162461bcd60e51b815260040161069290614f37565b610b8187876128bb565b6000610b8d8585612a76565b9050610b9a883383612a8a565b6004840154600090610bb2904263ffffffff612d6416565b9050610bc086858984613039565b6001600160a01b03891660009081526012602090815260408083208b8452909152902054610bf4908863ffffffff612d6416565b6001600160a01b038a1660009081526012602090815260408083208c8452909152902055610c228686612da6565b600187015560055485546001600160a01b0390811691161415610c8557336000908152600f6020908152604080832054815160608101909252602b808352610c85946001600160a01b0390921693919261091c928d929061520590830139612dd4565b6017546001600160a01b038a81169116148015610ca3575060185488145b15610d0b576016546040516337f23cd360e01b81526001600160a01b03909116906337f23cd390610cd8903390600401614bb9565b600060405180830381600087803b158015610cf257600080fd5b505af1158015610d06573d6000803e3d6000fd5b505050505b87896001600160a01b0316336001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e9464585604051610d4f9190614d0d565b60405180910390a487896001600160a01b0316336001600160a01b03167f88a254a0ef28a0b9e957ff600beae69870f6f924065147f3627c3f814e60ec118a604051610d9b9190614d0d565b60405180910390a450506003805460ff60a01b1916600160a01b17905550505050505050565b6000546001600160a01b03163314610deb5760405162461bcd60e51b815260040161069290614fa7565b610df48161321d565b50565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610e3057600080fd5b505afa158015610e44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610e689190810190613d12565b6001600160a01b0316336001600160a01b031614610e985760405162461bcd60e51b815260040161069290615027565b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610ed357600080fd5b505af1158015610ee7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f0b9190810190613fe5565b15610df45760405162461bcd60e51b815260040161069290614fb7565b604051610f3490614b95565b604051809103902081565b6004546001600160a01b031681565b6001546001600160a01b031681565b60066020526000908152604090205481565b6005546001600160a01b031681565b601560209081526000928352604080842090915290825290205481565b60096020526000908152604090205481565b600f602052600090815260409020546001600160a01b031681565b60135460ff1615610feb5760405162461bcd60e51b815260040161069290614e27565b610df433826132a2565b6002546001600160a01b031681565b6000546001600160a01b0316331461102e5760405162461bcd60e51b815260040161069290614fa7565b61103782613331565b61104081613331565b6005546004546001600160a01b03918216911681156110715760405162461bcd60e51b815260040161069290614ef7565b600580546001600160a01b038087166001600160a01b03199283161790925560048054928616929091169190911790556003805460ff60a01b1916600160a01b1790556040517f559f314bb90394a4a9ceb724f365b36a53587d894352c43d12901fd680101456906110ea908490849088908890614c2a565b60405180910390a150505050565b60006111048484612884565b6001600160a01b038085166000908152600a60209081526040808320878452825280832093861683529290522080545b600081118015611164575061116482600183038154811061115157fe5b9060005260206000209060020201613357565b156111a45761119982600183038154811061117b57fe5b6000918252602090912060029091020154849063ffffffff612d6416565b925060001901611134565b50509392505050565b60116020526000908152604090205463ffffffff1681565b60135460ff1681565b60004382106111ef5760405162461bcd60e51b815260040161069290614f07565b6001600160a01b03831660009081526011602052604090205463ffffffff168061121d5760009150506113d7565b6001600160a01b038416600090815260106020908152604080832063ffffffff600019860181168552925290912054168310611299576001600160a01b03841660009081526010602090815260408083206000199490940163ffffffff1683529290522054600160201b90046001600160601b031690506113d7565b6001600160a01b038416600090815260106020908152604080832083805290915290205463ffffffff168310156112d45760009150506113d7565b600060001982015b8163ffffffff168163ffffffff16111561139757600282820363ffffffff16048103611306613c85565b506001600160a01b038716600090815260106020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b03169181019190915290871415611372576020015194506113d79350505050565b805163ffffffff1687111561138957819350611390565b6001820392505b50506112dc565b506001600160a01b038516600090815260106020908152604080832063ffffffff909416835292905220546001600160601b03600160201b909104169150505b92915050565b600354600160a01b900460ff166114065760405162461bcd60e51b815260040161069290614f87565b6003805460ff60a01b1916905560135460ff16156114365760405162461bcd60e51b815260040161069290614e27565b6114408282612884565b6001600160a01b038216600090815260086020526040812080548390811061146457fe5b600091825260208083206001600160a01b038716808552600783526040808620888752845280862033808852908552818720928752600a85528187208988528552818720908752909352918420600590930201935091806114c5848461336c565b9092509050811515806114d85750600081115b6114f45760405162461bcd60e51b815260040161069290614fc7565b8115806114ff575080155b61151b5760405162461bcd60e51b815260040161069290614de7565b81156116345761152b87876128bb565b6000611571856001015461156564e8d4a510006115598a600301548a6000015461346390919063ffffffff16565b9063ffffffff61349d16565b9063ffffffff6134df16565b6004805460405163135b33cd60e31b81529293506001600160a01b031691639ad99e68916115a5918c913391879101614c02565b600060405180830381600087803b1580156115bf57600080fd5b505af11580156115d3573d6000803e3d6000fd5b505086546115ea925090508463ffffffff6134df16565b808655600387015461160d9164e8d4a5100091611559919063ffffffff61346316565b6001860155855461162e906001600160a01b0316338563ffffffff61352116565b506116b8565b8354611646908263ffffffff6134df16565b84556001600160a01b038716600090815260126020908152604080832089845290915290205461167c908263ffffffff6134df16565b6001600160a01b0380891660009081526012602090815260408083208b845290915290209190915585546116b89116338363ffffffff61352116565b856001600160a01b038816337fe31da05fae6db869f5ea51f4b638aa6884070b6c87f18f63bd2291a12cb2f5186116f5868663ffffffff612d6416565b6040516117029190614d0d565b60405180910390a450506003805460ff60a01b1916600160a01b1790555050505050565b600e6020526000908152604090205481565b6117766040518060400160405280601c81526020017f73657428616464726573732c75696e743235362c75696e7432353629000000008152506127e2565b6117808383612884565b61178983613543565b6001600160a01b038316600090815260086020526040812080549091906118029084906117f6908590889081106117bc57fe5b60009182526020808320600160059093020191909101546001600160a01b038b16835260099091526040909120549063ffffffff6134df16565b9063ffffffff612d6416565b9050600081116118245760405162461bcd60e51b815260040161069290615037565b600082858154811061183257fe5b90600052602060002090600502016001015490508383868154811061185357fe5b9060005260206000209060050201600101819055508160096000886001600160a01b03166001600160a01b031681526020019081526020016000208190555084866001600160a01b03167f6ee09c6cb801194690c195c69f465aaf7c80255cbeafaab9600f47ed79de2ca983876040516118ce929190615062565b60405180910390a3505050505050565b611906604051806040016040528060078152602001667061757365282960c81b8152506127e2565b60135460ff16156119295760405162461bcd60e51b815260040161069290614eb7565b6013805460ff1916600117905560405133907fdffada2889ebfab9224c24069d833f3de835d8cf99872d49e7b7ba5fccb7a46f90600090a2565b60135460ff16156119865760405162461bcd60e51b815260040161069290614e27565b6119908282612884565b61199a82826128bb565b5050565b600860205281600052604060002081815481106119b757fe5b6000918252602090912060059091020180546001820154600283015460038401546004909401546001600160a01b039093169550909350919085565b611a146040518060600160405280602881526020016152b1602891396127e2565b60048054604051633d6ac5b360e21b81526001600160a01b039091169163f5ab16cc91611a4391869101614bab565b60206040518083038186803b158015611a5b57600080fd5b505afa158015611a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611a939190810190613f88565b611aaf5760405162461bcd60e51b815260040161069290614f97565b611ab882613543565b6001600160a01b0382166000818152600660205260409081902080549084905590519091907fad96cee0d692f0250b98e085504f399da6733854908215f6203fe3c69366d9f590611b0c9084908690615062565b60405180910390a2505050565b6000806000611b288686612884565b5050506001600160a01b03928316600090815260076020908152604080832094835293815283822092909416815292529020805460018201546002909201549092565b600354600160a01b900460ff16611b945760405162461bcd60e51b815260040161069290614f87565b6003805460ff60a01b1916905560135460ff1615611bc45760405162461bcd60e51b815260040161069290614e27565b611bce8282612884565b6001600160a01b0382166000908152600860205260408120805483908110611bf257fe5b600091825260208083206001600160a01b0380881685526007835260408086208887528452808620918a1686529252922060059091029091019150611c3784846128bb565b611c4284848761202d565b15611c5f5760405162461bcd60e51b815260040161069290614f37565b805415611ce3576000611c728284612a76565b90508015611ce157611c848284612da6565b6001830155611c94858783612a8a565b83856001600160a01b0316876001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e9464584604051611cd89190614d0d565b60405180910390a45b505b50506003805460ff60a01b1916600160a01b179055505050565b611d1e6040518060600160405280603381526020016152d9603391396127e2565b611d288383612884565b600081118015611d3b57506312cc030081105b611d575760405162461bcd60e51b815260040161069290614fd7565b6001600160a01b0383166000908152600860205260408120805484908110611d7b57fe5b9060005260206000209060050201905060008160040154905082826004018190555083856001600160a01b03167f0bcf80c5060ccf99b7a993c57a94b232fc2c5c04bd74c7c7d174595fee6bc31f8386604051611dd9929190615062565b60405180910390a35050505050565b6000611df48484612884565b6001600160a01b0384166000908152600860205260408120805485908110611e1857fe5b600091825260208083206001600160a01b03808a168086526007845260408087208b885285528087208a8416885285528087206003600590970290940195860154918752601285528087208b885290945283862054855494516370a0823160e01b8152959750929590949093611eef939216906370a0823190611e9f903090600401614bab565b60206040518083038186803b158015611eb757600080fd5b505afa158015611ecb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115659190810190613fe5565b6001600160a01b0389166000908152600660205260409020546002860154919250439182118015611f1f57508215155b15611fb5576000611f3d8760020154846134df90919063ffffffff16565b6001600160a01b038c1660009081526009602052604081205460018a01549293509091611f85919061155990611f79868863ffffffff61346316565b9063ffffffff61346316565b9050611fb0611fa3866115598464e8d4a5100063ffffffff61346316565b879063ffffffff612d6416565b955050505b6001600160a01b03808b166000908152600a602090815260408083208d84528252808320938c16835292905290812090611fee82612f95565b91505061201d876001015461156564e8d4a510006115598a611f79878e600001546134df90919063ffffffff16565b9c9b505050505050505050505050565b6001600160a01b038084166000908152600a602090815260408083208684528252808320938516835292905290812061206581612f95565b5095945050505050565b6017546001600160a01b031681565b6047546001600160a01b031690565b6001600160a01b03811660009081526011602052604081205463ffffffff16806120b85760006120f7565b6001600160a01b0383166000908152601060209081526040808320600019850163ffffffff168452909152902054600160201b90046001600160601b03165b9150505b919050565b606061210c8484612884565b6001600160a01b038085166000908152600a602090815260408083208784528252808320938616835292815282822080548451818402810184019095528085529092909184015b828210156121ad5760008481526020908190206040805160608101825260028602909201805483526001908101546001600160801b0380821685870152600160801b90910416918301919091529083529092019101612153565b5050505090509392505050565b60146020526000908152604090205460ff1681565b60135460ff16156121f25760405162461bcd60e51b815260040161069290614e27565b600060405161220090614b95565b604080519182900382208282019091526008825267161594d5985d5b1d60c21b6020909201919091527fddfcc46608a8bd52ebf900f03a24cc97b73a6046cec8c5d0f74a211e376e967a612252613578565b306040516020016122669493929190614d29565b604051602081830303815290604052805190602001209050600060405161228c90614ba0565b6040519081900381206122a7918a908a908a90602001614d1b565b604051602081830303815290604052805190602001209050600082826040516020016122d4929190614b64565b60405160208183030381529060405280519060200120905060006122fa8288888861357c565b6001600160a01b0381166000908152600e60205260409020805460018101909155909150891461233c5760405162461bcd60e51b815260040161069290614e97565b8742111561235c5760405162461bcd60e51b815260040161069290614e77565b612366818b6132a2565b505050505b505050505050565b6001600160a01b031660009081526008602052604090205490565b6000546001600160a01b031633146123b85760405162461bcd60e51b815260040161069290614fa7565b6001600160a01b0383166123de5760405162461bcd60e51b815260040161069290614e87565b6001600160a01b0382166124045760405162461bcd60e51b815260040161069290614f17565b61240e8282612884565b6016546017546018546040516001600160a01b03808816948116937f8def9436d6e31b89ed00948ba91d0cb6936eada5154cb1b45b55683fb9e492379361245d93919092169188918890614c83565b60405180910390a3601680546001600160a01b039485166001600160a01b0319918216179091556017805493909416921691909117909155601855565b6003546001600160a01b031681565b604051610f3490614ba0565b60185481565b601060209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6312cc030081565b6000546001600160a01b031681565b6125286040518060600160405280602c8152602001615338602c91396127e2565b61253185613331565b61253a83613331565b6004546001600160a01b03166125625760405162461bcd60e51b815260040161069290614e07565b600084116125825760405162461bcd60e51b815260040161069290614fe7565b61258b85613543565b6001600160a01b0385166000908152600860205260408120805490915b8181101561260657856001600160a01b03168382815481106125c657fe5b60009182526020909120600590910201546001600160a01b031614156125fe5760405162461bcd60e51b815260040161069290614f77565b6001016125a8565b506001600160a01b03851660009081526014602052604090205460ff16156126405760405162461bcd60e51b815260040161069290614ee7565b6001600160a01b038716600090815260096020526040902054612669908763ffffffff612d6416565b6001600160a01b0388811660009081526009602090815260408083209490945560068152838220889055835160a0810185528984168082528183018c81524383880190815260608401868152608085018c81528b5460018082018e558d8a52888a209751600590920290970180546001600160a01b031916918b169190911781559351848701559151600284015551600383015551600491820155908452601490925291849020805460ff1916831790558054935163fb66fb4d60e01b8152939092169263fb66fb4d92612741928c92909101614cb8565b600060405180830381600087803b15801561275b57600080fd5b505af115801561276f573d6000803e3d6000fd5b50505050846001600160a01b03166001838054905003886001600160a01b03167fd7fa4bff1cd2253c0789c3291a786a6f6b1a3b4569a75af683a15d52abb6a0bf8988886040516127c293929190615070565b60405180910390a450505050505050565b6016546001600160a01b031681565b6047546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906128159033908690600401614bc7565b60206040518083038186803b15801561282d57600080fd5b505afa158015612841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506128659190810190613f88565b90508061199a5760405162461bcd60e51b815260040161069290614e47565b6001600160a01b038216600090815260086020526040902054811061199a5760405162461bcd60e51b815260040161069290614df7565b6001600160a01b03821660009081526008602052604081208054839081106128df57fe5b9060005260206000209060050201905080600201544311612900575061199a565b80546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612930903090600401614bab565b60206040518083038186803b15801561294857600080fd5b505afa15801561295c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506129809190810190613fe5565b6001600160a01b03851660009081526012602090815260408083208784529091529020549091506129b890829063ffffffff6134df16565b9050806129cc57504360029091015561199a565b600282015443906000906129e790839063ffffffff6134df16565b6001600160a01b03871660009081526009602090815260408083205460018901546006909352908320549394509192612a30929161155991611f7990879063ffffffff61346316565b9050612a5f612a4e856115598464e8d4a5100063ffffffff61346316565b60038701549063ffffffff612d6416565b600386015550504360029093019290925550505050565b600061071183600101546115658585612da6565b600480546040516370a0823160e01b81526001600160a01b03918216926000928716916370a0823191612abf91869101614bab565b60206040518083038186803b158015612ad757600080fd5b505afa158015612aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612b0f9190810190613fe5565b6001600160a01b038087166000908152601560209081526040808320938916835292905290812054919250612b4a858363ffffffff612d6416565b9050828111612c28578115612bbd576001600160a01b038088166000818152601560209081526040808320948b1680845294909152808220829055517f6bdfd5e51d01475945224d3d37965916fd8df699ef9e8888af4359aa8622216091612bb491879190615047565b60405180910390a35b60405163135b33cd60e31b81526001600160a01b03851690639ad99e6890612bed908a908a908690600401614c68565b600060405180830381600087803b158015612c0757600080fd5b505af1158015612c1b573d6000803e3d6000fd5b5050505050505050612cfe565b6001600160a01b038088166000818152601560209081526040808320948b168084529490915290819020868503908190559051909291907f6bdfd5e51d01475945224d3d37965916fd8df699ef9e8888af4359aa8622216090612c8e9087908690615062565b60405180910390a360405163135b33cd60e31b81526001600160a01b03861690639ad99e6890612cc6908b908b908990600401614c68565b600060405180830381600087803b158015612ce057600080fd5b505af1158015612cf4573d6000803e3d6000fd5b5050505050505050505b505050565b604051612d5e9085906323b872dd60e01b90612d2790879087908790602401614c68565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526135a6565b50505050565b600061071183836040518060400160405280601b81526020017f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525061368b565b600061071164e8d4a510006115598460030154611f79876002015488600001546134df90919063ffffffff16565b600081600160601b8410612dfb5760405162461bcd60e51b81526004016106929190614dc6565b509192915050565b816001600160a01b0316836001600160a01b031614158015612e2e57506000816001600160601b0316115b15612cfe576001600160a01b03831615612ee6576001600160a01b03831660009081526011602052604081205463ffffffff169081612e6e576000612ead565b6001600160a01b0385166000908152601060209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b90506000612ed482856040518060600160405280602c815260200161530c602c91396136bb565b9050612ee2868484846136fa565b5050505b6001600160a01b03821615612cfe576001600160a01b03821660009081526011602052604081205463ffffffff169081612f21576000612f60565b6001600160a01b0384166000908152601060209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b90506000612f8782856040518060600160405280602b81526020016151da602b91396138af565b905061236b858484846136fa565b805460009081905b801561303357836001820381548110612fb257fe5b6000918252602090912060016002909202018101546001600160801b03600160801b9091041614156130155761300e846001830381548110612ff057fe5b6000918252602090912060029091020154839063ffffffff612d6416565b915061302a565b61302784600183038154811061117b57fe5b92505b60001901612f9d565b50915091565b8254604080516060810182526000808252602080830182815260019484018581528587018a5589845291909220925160028602909301928355905191909201805492516001600160801b03908116600160801b029281166001600160801b0319909416939093179092161790555b6000811180156130e25750818460018303815481106130c257fe5b60009182526020909120600160029092020101546001600160801b031611155b15613169578360018203815481106130f657fe5b906000526020600020906002020184828154811061311057fe5b600091825260209091208254600290920201908155600191820180549290910180546001600160801b0319166001600160801b03938416178082559154600160801b9081900484160291909216179055600019016130a7565b6040518060600160405280848152602001613183846138e2565b6001600160801b0316815260200160016001600160801b03168152508482815481106131ab57fe5b60009182526020918290208351600292830290910190815591830151600190920180546040909401516001600160801b03199094166001600160801b03938416178316600160801b939094169290920292909217905585015461320e9084612d64565b85600201819055505050505050565b6001600160a01b0381166132435760405162461bcd60e51b815260040161069290614ec7565b604780546001600160a01b038381166001600160a01b03198316179092556040519116907f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0906132969083908590614be7565b60405180910390a15050565b6001600160a01b038083166000908152600f6020526040812054909116906132c98461390b565b6001600160a01b038581166000818152600f602052604080822080546001600160a01b031916898616908117909155905194955093928616927f0cc323ffec3ea49cbcddc0de1480978126d350c6a45dff33ad2f1cda6ae992619190a4612d5e828483612e03565b6001600160a01b038116610df45760405162461bcd60e51b815260040161069290614f27565b60010154426001600160801b03909116111590565b805460009081905b600081118015613391575061339184600183038154811061115157fe5b15613432578360018203815481106133a557fe5b6000918252602090912060016002909202018101546001600160801b03600160801b9091041614156133ea576133e3846001830381548110612ff057fe5b91506133ff565b6133fc84600183038154811061117b57fe5b92505b8380548061340957fe5b600082815260208120600019928301600281029091018281556001019190915590915501613374565b50613457613446828463ffffffff612d6416565b60028601549063ffffffff6134df16565b60028501559250929050565b600082613472575060006113d7565b8282028284828161347f57fe5b04146107115760405162461bcd60e51b815260040161069290614f67565b600061071183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613a21565b600061071183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613a58565b604051612cfe90849063a9059cbb60e01b90612d279086908690602401614cd3565b6001600160a01b038116600090815260086020526040812054905b81811015612cfe5761357083826128bb565b60010161355e565b4690565b600080600061358d87878787613a7c565b9150915061359a81613b5c565b5090505b949350505050565b6135b8826001600160a01b0316613c25565b6135d45760405162461bcd60e51b815260040161069290615007565b60006060836001600160a01b0316836040516135f09190614b58565b6000604051808303816000865af19150503d806000811461362d576040519150601f19603f3d011682016040523d82523d6000602084013e613632565b606091505b5091509150816136545760405162461bcd60e51b815260040161069290614ff7565b805115612d5e578080602001905161366f9190810190613f88565b612d5e5760405162461bcd60e51b815260040161069290614e67565b600083830182858210156136b25760405162461bcd60e51b81526004016106929190614dc6565b50949350505050565b6000836001600160601b0316836001600160601b0316111582906136f25760405162461bcd60e51b81526004016106929190614dc6565b505050900390565b600061371e4360405180606001604052806038815260200161527960389139613c5e565b905060008463ffffffff1611801561376757506001600160a01b038516600090815260106020908152604080832063ffffffff6000198901811685529252909120548282169116145b156137c6576001600160a01b0385166000908152601060209081526040808320600019880163ffffffff168452909152902080546fffffffffffffffffffffffff000000001916600160201b6001600160601b03851602179055613865565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000818152601083528781208c871682528352878120965187549451909516600160201b026fffffffffffffffffffffffff000000001995871663ffffffff19958616179590951694909417909555938252601190935292909220805460018801909316929091169190911790555b846001600160a01b03167f6adb589fed1e8542fb7a6b10f00a85e02265e77f9ae3ca8ff93b22983e1af9a084846040516138a09291906150c2565b60405180910390a25050505050565b6000838301826001600160601b0380871690831610156136b25760405162461bcd60e51b81526004016106929190614dc6565b6000600160801b82106139075760405162461bcd60e51b815260040161069290614ea7565b5090565b6005546000906001600160a01b03166139365760405162461bcd60e51b815260040161069290614e57565b6005546001600160a01b03166000908152600860205260408120805490915b81811015613a165760055483546001600160a01b039091169084908390811061397a57fe5b60009182526020909120600590910201546001600160a01b03161415613a0e576005546001600160a01b039081166000908152600760209081526040808320858452825280832093891683529290522060028101548154613a03916139e5919063ffffffff6134df16565b60405180606001604052806028815260200161523060289139612dd4565b9450505050506120fb565b600101613955565b506000949350505050565b60008183613a425760405162461bcd60e51b81526004016106929190614dc6565b506000838581613a4e57fe5b0495945050505050565b600081848411156136f25760405162461bcd60e51b81526004016106929190614dc6565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613ab35750600090506003613b53565b8460ff16601b14158015613acb57508460ff16601c14155b15613adc5750600090506004613b53565b600060018787878760405160008152602001604052604051613b019493929190614d51565b6020604051602081039080840390855afa158015613b23573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613b4c57506000915060019050613b53565b9150600090505b94509492505050565b6000816004811115613b6a57fe5b1415613b7557610df4565b6001816004811115613b8357fe5b1415613ba15760405162461bcd60e51b815260040161069290614dd7565b6002816004811115613baf57fe5b1415613bcd5760405162461bcd60e51b815260040161069290614e17565b6003816004811115613bdb57fe5b1415613bf95760405162461bcd60e51b815260040161069290614ed7565b6004816004811115613c0757fe5b1415610df45760405162461bcd60e51b815260040161069290614f47565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061359e575050151592915050565b600081600160201b8410612dfb5760405162461bcd60e51b81526004016106929190614dc6565b604080518082019091526000808252602082015290565b80356113d781615198565b80516113d781615198565b80516113d7816151ac565b80356113d7816151b5565b80356113d7816151be565b80516113d7816151b5565b80356113d7816151c7565b80356113d7816151d0565b600060208284031215613d0657600080fd5b600061359e8484613c9c565b600060208284031215613d2457600080fd5b600061359e8484613ca7565b60008060408385031215613d4357600080fd5b6000613d4f8585613c9c565b9250506020613d6085828601613c9c565b9150509250929050565b600080600060608486031215613d7f57600080fd5b6000613d8b8686613c9c565b9350506020613d9c86828701613c9c565b9250506040613dad86828701613cbd565b9150509250925092565b60008060408385031215613dca57600080fd5b6000613dd68585613c9c565b9250506020613d6085828601613cbd565b600080600060608486031215613dfc57600080fd5b6000613e088686613c9c565b9350506020613e1986828701613cbd565b9250506040613dad86828701613c9c565b600080600080600060a08688031215613e4257600080fd5b6000613e4e8888613c9c565b9550506020613e5f88828901613cbd565b9450506040613e7088828901613cc8565b9350506060613e8188828901613cbd565b9250506080613e9288828901613cbd565b9150509295509295909350565b600080600060608486031215613eb457600080fd5b6000613ec08686613c9c565b9350506020613d9c86828701613cbd565b60008060008060008060c08789031215613eea57600080fd5b6000613ef68989613c9c565b9650506020613f0789828a01613cbd565b9550506040613f1889828a01613cbd565b9450506060613f2989828a01613ce9565b9350506080613f3a89828a01613cbd565b92505060a0613f4b89828a01613cbd565b9150509295509295509295565b60008060408385031215613f6b57600080fd5b6000613f778585613c9c565b9250506020613d6085828601613cde565b600060208284031215613f9a57600080fd5b600061359e8484613cb2565b600080600060608486031215613fbb57600080fd5b6000613d8b8686613cc8565b600060208284031215613fd957600080fd5b600061359e8484613cc8565b600060208284031215613ff757600080fd5b600061359e8484613cd3565b600061400f8383614af8565b505060600190565b61402081615141565b82525050565b614020816150f0565b600061403a826150e3565b61404481856150e7565b935061404f836150dd565b8060005b8381101561407d5781516140678882614003565b9750614072836150dd565b925050600101614053565b509495945050505050565b614020816150fb565b61402081615100565b6140206140a682615100565b615100565b60006140b6826150e3565b6140c081856120fb565b93506140d0818560208601615162565b9290920192915050565b61402081615103565b6140208161514c565b60006140f7826150e3565b61410181856150e7565b9350614111818560208601615162565b61411a8161518e565b9093019392505050565b60006141316018836150e7565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000815260200192915050565b600061416a6012836150e7565b71696e636f6e73697374656e7420737461746560701b815260200192915050565b60006141986013836150e7565b727661756c743a20706f6f6c206578697374733f60681b815260200192915050565b60006141c7601f836150e7565b7f53746f726520636f6e7472616374206164647265737320697320656d70747900815260200192915050565b6000614200601f836150e7565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800815260200192915050565b6000614239600f836150e7565b6e15985d5b1d081a5cc81c185d5cd959608a1b815260200192915050565b60006142646013836150e7565b7215985d5b1d081a5cc81b9bdd081c185d5cd959606a1b815260200192915050565b6000614293600c836150e7565b6b155b985d5d1a1bdc9a5e995960a21b815260200192915050565b60006142bb6030836150e7565b7f5856535661756c743a3a6765745374616b65416d6f756e743a2078767320616481526f191c995cdcc81a5cc81b9bdd081cd95d60821b602082015260400192915050565b600061430d602a836150e7565b7f5361666542455032303a204245503230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b602082015260400192915050565b6000614359602a836150e7565b7f5856535661756c743a3a64656c656761746542795369673a207369676e6174758152691c9948195e1c1a5c995960b21b602082015260400192915050565b60006143a56022836150e7565b7f7072696d6520746f6b656e2063616e6e6f74206265207a65726f206164647265815261737360f01b602082015260400192915050565b60006143e96026836150e7565b7f5856535661756c743a3a64656c656761746542795369673a20696e76616c6964815265206e6f6e636560d01b602082015260400192915050565b60006144316002836120fb565b61190160f01b815260020192915050565b600061444f6027836150e7565b7f53616665436173743a2076616c756520646f65736e27742066697420696e20318152663238206269747360c81b602082015260400192915050565b60006144986017836150e7565b7f5661756c7420697320616c726561647920706175736564000000000000000000815260200192915050565b60006144d16025836150e7565b7f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164815264647265737360d81b602082015260400192915050565b60006145186022836150e7565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c815261756560f01b602082015260400192915050565b600061455c601a836150e7565b7f546f6b656e2065786973747320696e206f7468657220706f6f6c000000000000815260200192915050565b60006145956013836150e7565b72185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b815260200192915050565b60006145c4602b836150e7565b7f5856535661756c743a3a6765745072696f72566f7465733a206e6f742079657481526a0819195d195c9b5a5b995960aa1b602082015260400192915050565b6000614611601d836150e7565b7f7265776172642063616e6e6f74206265207a65726f2061646472657373000000815260200192915050565b600061464a6018836150e7565b7f7a65726f2061646472657373206e6f7420616c6c6f7765640000000000000000815260200192915050565b6000614683601a836150e7565b7f657865637574652070656e64696e67207769746864726177616c000000000000815260200192915050565b60006146bc6022836150e7565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c815261756560f01b602082015260400192915050565b60006147006043836120fb565b7f454950373132446f6d61696e28737472696e67206e616d652c75696e7432353681527f20636861696e49642c6164647265737320766572696679696e67436f6e74726160208201526263742960e81b604082015260430192915050565b600061476b601f836150e7565b7f72657175657374656420616d6f756e742063616e6e6f74206265207a65726f00815260200192915050565b60006147a46021836150e7565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b60006147e76012836150e7565b71141bdbdb08185b1c9958591e48185919195960721b815260200192915050565b6000614815600a836150e7565b691c994b595b9d195c995960b21b815260200192915050565b600061483b6014836150e7565b7324b73b30b634b2103932bbb0b932103a37b5b2b760611b815260200192915050565b600061486b600e836150e7565b6d37b7363c9030b236b4b71031b0b760911b815260200192915050565b60006148956015836150e7565b7418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b815260200192915050565b60006148c66013836150e7565b726e6f7468696e6720746f20776974686472617760681b815260200192915050565b60006148f5601a836150e7565b7f496e76616c6964206e6577206c6f636b696e6720706572696f64000000000000815260200192915050565b600061492e601d836150e7565b7f416c6c6f6320706f696e7473206d757374206e6f74206265207a65726f000000815260200192915050565b60006149676020836150e7565b7f5361666542455032303a206c6f772d6c6576656c2063616c6c206661696c6564815260200192915050565b60006149a0603a836120fb565b7f44656c65676174696f6e28616464726573732064656c6567617465652c75696e81527f74323536206e6f6e63652c75696e7432353620657870697279290000000000006020820152603a0192915050565b60006149ff601f836150e7565b7f5361666542455032303a2063616c6c20746f206e6f6e2d636f6e747261637400815260200192915050565b6000614a38601b836150e7565b7f72657175657374656420616d6f756e7420697320696e76616c69640000000000815260200192915050565b6000614a716022836150e7565b7f6f6e6c792070726f78792061646d696e2063616e206368616e676520627261698152616e7360f01b602082015260400192915050565b6000614ab5602e836150e7565b7f416c6c6f6320706f696e7473207065722072657761726420746f6b656e206d7581526d7374206e6f74206265207a65726f60901b602082015260400192915050565b80516060830190614b098482614091565b506020820151614b1c6020850182614b2b565b506040820151612d5e60408501825b6140208161510e565b61402081615126565b6140208161512f565b61402081615157565b61402081615135565b600061071182846140ab565b6000614b6f82614424565b9150614b7b828561409a565b602082019150614b8b828461409a565b5060200192915050565b60006113d7826146f3565b60006113d782614993565b602081016113d78284614026565b602081016113d78284614017565b60408101614bd58285614017565b818103602083015261359e81846140ec565b60408101614bf58285614026565b6107116020830184614026565b60608101614c108286614026565b614c1d6020830185614017565b61359e6040830184614091565b60808101614c388287614026565b614c456020830186614026565b614c526040830185614026565b614c5f6060830184614026565b95945050505050565b60608101614c768286614026565b614c1d6020830185614026565b60808101614c918287614026565b614c9e6020830186614026565b614cab6040830185614091565b614c5f6060830184614091565b60408101614cc68285614026565b6107116020830184614088565b60408101614ce18285614026565b6107116020830184614091565b60208082528101610711818461402f565b602081016113d78284614088565b602081016113d78284614091565b60808101614c918287614091565b60808101614d378287614091565b614d446020830186614091565b614c526040830185614091565b60808101614d5f8287614091565b614c9e6020830186614b3d565b602081016113d782846140da565b60a08101614d8882886140da565b614d956020830187614091565b614da26040830186614091565b614daf6060830185614091565b614dbc6080830184614091565b9695505050505050565b6020808252810161071181846140ec565b602080825281016113d781614124565b602080825281016113d78161415d565b602080825281016113d78161418b565b602080825281016113d7816141ba565b602080825281016113d7816141f3565b602080825281016113d78161422c565b602080825281016113d781614257565b602080825281016113d781614286565b602080825281016113d7816142ae565b602080825281016113d781614300565b602080825281016113d78161434c565b602080825281016113d781614398565b602080825281016113d7816143dc565b602080825281016113d781614442565b602080825281016113d78161448b565b602080825281016113d7816144c4565b602080825281016113d78161450b565b602080825281016113d78161454f565b602080825281016113d781614588565b602080825281016113d7816145b7565b602080825281016113d781614604565b602080825281016113d78161463d565b602080825281016113d781614676565b602080825281016113d7816146af565b602080825281016113d78161475e565b602080825281016113d781614797565b602080825281016113d7816147da565b602080825281016113d781614808565b602080825281016113d78161482e565b602080825281016113d78161485e565b602080825281016113d781614888565b602080825281016113d7816148b9565b602080825281016113d7816148e8565b602080825281016113d781614921565b602080825281016113d78161495a565b602080825281016113d7816149f2565b602080825281016113d781614a2b565b602080825281016113d781614a64565b602080825281016113d781614aa8565b604081016150558285614091565b61071160208301846140e3565b60408101614ce18285614091565b6060810161507e8286614091565b614c1d6020830185614091565b602081016113d78284614b34565b604081016150a78285614b34565b6107116020830184614b4f565b602081016113d78284614b4f565b604081016150d08285614b46565b6107116020830184614b46565b60200190565b5190565b90815260200190565b60006113d78261511a565b151590565b90565b60006113d7826150f0565b6001600160801b031690565b6001600160a01b031690565b63ffffffff1690565b60ff1690565b6001600160601b031690565b60006113d782615103565b60006113d782615100565b60006113d782615135565b60005b8381101561517d578181015183820152602001615165565b83811115612d5e5750506000910152565b601f01601f191690565b6151a1816150f0565b8114610df457600080fd5b6151a1816150fb565b6151a181615100565b6151a181615103565b6151a181615126565b6151a18161512f56fe5856535661756c743a3a5f6d6f7665566f7465733a20766f746520616d6f756e74206f766572666c6f77735856535661756c743a3a726571756573745769746864726177616c3a20766f746573206f766572666c6f775856535661756c743a3a6765745374616b65416d6f756e743a20766f746573206f766572666c6f775856535661756c743a3a6465706f7369743a20766f746573206f766572666c6f775856535661756c743a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d62657220657863656564732033322062697473736574526577617264416d6f756e74506572426c6f636b28616464726573732c75696e74323536297365745769746864726177616c4c6f636b696e67506572696f6428616464726573732c75696e743235362c75696e74323536295856535661756c743a3a5f6d6f7665566f7465733a20766f746520616d6f756e7420756e646572666c6f777361646428616464726573732c75696e743235362c616464726573732c75696e743235362c75696e7432353629a365627a7a723158206fcd6577817fe07166c8f22ad5e6c4a8771a4690f6356182a14a0bf96f9a45af6c6578706572696d656e74616cf564736f6c63430005100040", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106102bb5760003560e01c80638456cb5911610182578063c2102596116100e9578063e7a324dc116100a2578063f55401621161007c578063f55401621461061c578063f851a44014610624578063fba1b1f91461062c578063fe5a451a1461063f576102bb565b8063e7a324dc146105eb578063e8f2be6f146105f3578063f1127ed8146105fb576102bb565b8063c210259614610577578063c3c754a814610597578063c3cda520146105aa578063d7ae45e2146105bd578063dae66bbe146105d0578063de0368b2146105e3576102bb565b80639e2b6c4d1161013b5780639e2b6c4d1461050e578063a09eab7a14610521578063a9d69a6914610534578063add8933714610547578063b4a0bdf31461054f578063b4b5ea5714610564576102bb565b80638456cb59146104875780638ed7333d1461048f57806392e35000146104a257806393c7c4d1146104c657806398e1b31b146104d9578063996cba68146104fb576102bb565b80634298bdbd116102265780636fcfff45116101df5780636fcfff45146103f957806373d025d614610419578063782d6fe11461042e5780637ac924561461044e5780637ecebe00146104615780638308d7e914610474576102bb565b80634298bdbd14610392578063587cde1e146103a55780635c19a95c146103b85780635c60da1b146103cb5780635ff56315146103d35780636dd77cbd146103e6576102bb565b806320606b701161027857806320606b701461033f57806324f52bbf14610347578063267822471461035c5780632eda5c6c14610364578063358ae036146103775780633d4180f91461037f576102bb565b8063046f7da2146102c05780630af13728146102ca5780630efe6a8b146102f3578063115b512f1461030657806319129e5a146103195780631d504dc61461032c575b600080fd5b6102c8610647565b005b6102dd6102d8366004613de7565b6106d2565b6040516102ea9190614d0d565b60405180910390f35b6102c8610301366004613e9f565b610718565b6102c8610314366004613e9f565b610a0d565b6102c8610327366004613cf4565b610dc1565b6102c861033a366004613fc7565b610df7565b6102dd610f28565b61034f610f3f565b6040516102ea9190614bab565b61034f610f4e565b6102dd610372366004613cf4565b610f5d565b61034f610f6f565b6102dd61038d366004613d30565b610f7e565b6102dd6103a0366004613cf4565b610f9b565b61034f6103b3366004613cf4565b610fad565b6102c86103c6366004613cf4565b610fc8565b61034f610ff5565b6102c86103e1366004613d30565b611004565b6102dd6103f4366004613de7565b6110f8565b61040c610407366004613cf4565b6111ad565b6040516102ea919061508b565b6104216111c5565b6040516102ea9190614cff565b61044161043c366004613db7565b6111ce565b6040516102ea91906150b4565b6102c861045c366004613db7565b6113dd565b6102dd61046f366004613cf4565b611726565b6102c8610482366004613e9f565b611738565b6102c86118de565b6102c861049d366004613db7565b611963565b6104b56104b0366004613db7565b61199e565b6040516102ea959493929190614d7a565b6102c86104d4366004613db7565b6119f3565b6104ec6104e7366004613de7565b611b19565b6040516102ea93929190615070565b6102c8610509366004613d6a565b611b6b565b6102c861051c366004613e9f565b611cfd565b6102dd61052f366004613de7565b611de8565b6102dd610542366004613de7565b61202d565b61034f61206f565b61055761207e565b6040516102ea9190614d6c565b610441610572366004613cf4565b61208d565b61058a610585366004613de7565b612100565b6040516102ea9190614cee565b6104216105a5366004613cf4565b6121ba565b6102c86105b8366004613ed1565b6121cf565b6102dd6105cb366004613cf4565b612373565b6102c86105de366004613fa6565b61238e565b61034f61249a565b6102dd6124a9565b6102dd6124b5565b61060e610609366004613f58565b6124bb565b6040516102ea929190615099565b6102dd6124f0565b61034f6124f8565b6102c861063a366004613e2a565b612507565b6105576127d3565b61067060405180604001604052806008815260200167726573756d65282960c01b8152506127e2565b60135460ff1661069b5760405162461bcd60e51b815260040161069290614e37565b60405180910390fd5b6013805460ff1916905560405133907fd2619572a1464e0df0bb351d834fd47f3350984d7bfdb1ab69cfcb0b8e42141590600090a2565b60006106de8484612884565b506001600160a01b0380841660009081526007602090815260408083208684528252808320938516835292905220600201545b9392505050565b600354600160a01b900460ff166107415760405162461bcd60e51b815260040161069290614f87565b6003805460ff60a01b1916905560135460ff16156107715760405162461bcd60e51b815260040161069290614e27565b61077b8383612884565b6001600160a01b038316600090815260086020526040812080548490811061079f57fe5b600091825260208083206001600160a01b038816845260078252604080852088865283528085203386529092529220600590910290910191506107e285856128bb565b6107ed85853361202d565b1561080a5760405162461bcd60e51b815260040161069290614f37565b80541561087f57600061081d8284612a76565b9050801561087d57610830863383612a8a565b84866001600160a01b0316336001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e94645846040516108749190614d0d565b60405180910390a45b505b815461089c906001600160a01b031633308663ffffffff612d0316565b80546108ae908463ffffffff612d6416565b81556108ba8183612da6565b600182015560055482546001600160a01b039081169116141561092157336000908152600f6020908152604080832054815160608101909252602180835261092194936001600160a01b039092169261091c9289929061525890830139612dd4565b612e03565b6017546001600160a01b03868116911614801561093f575060185484145b156109a7576016546040516337f23cd360e01b81526001600160a01b03909116906337f23cd390610974903390600401614bb9565b600060405180830381600087803b15801561098e57600080fd5b505af11580156109a2573d6000803e3d6000fd5b505050505b83856001600160a01b0316336001600160a01b03167fdcbc1c05240f31ff3ad067ef1ee35ce4997762752e3a095284754544f4c709d7866040516109eb9190614d0d565b60405180910390a450506003805460ff60a01b1916600160a01b179055505050565b600354600160a01b900460ff16610a365760405162461bcd60e51b815260040161069290614f87565b6003805460ff60a01b1916905560135460ff1615610a665760405162461bcd60e51b815260040161069290614e27565b610a708383612884565b60008111610a905760405162461bcd60e51b815260040161069290614f57565b6001600160a01b0383166000908152600760209081526040808320858452825280832033845290915290206002810154610ad0908363ffffffff612d6416565b81541015610af05760405162461bcd60e51b815260040161069290615017565b6001600160a01b0384166000908152600860205260408120805485908110610b1457fe5b600091825260208083206001600160a01b0389168452600a825260408085208986528352808520338652909252908320600590920201925090610b5682612f95565b5090508015610b775760405162461bcd60e51b815260040161069290614f37565b610b8187876128bb565b6000610b8d8585612a76565b9050610b9a883383612a8a565b6004840154600090610bb2904263ffffffff612d6416565b9050610bc086858984613039565b6001600160a01b03891660009081526012602090815260408083208b8452909152902054610bf4908863ffffffff612d6416565b6001600160a01b038a1660009081526012602090815260408083208c8452909152902055610c228686612da6565b600187015560055485546001600160a01b0390811691161415610c8557336000908152600f6020908152604080832054815160608101909252602b808352610c85946001600160a01b0390921693919261091c928d929061520590830139612dd4565b6017546001600160a01b038a81169116148015610ca3575060185488145b15610d0b576016546040516337f23cd360e01b81526001600160a01b03909116906337f23cd390610cd8903390600401614bb9565b600060405180830381600087803b158015610cf257600080fd5b505af1158015610d06573d6000803e3d6000fd5b505050505b87896001600160a01b0316336001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e9464585604051610d4f9190614d0d565b60405180910390a487896001600160a01b0316336001600160a01b03167f88a254a0ef28a0b9e957ff600beae69870f6f924065147f3627c3f814e60ec118a604051610d9b9190614d0d565b60405180910390a450506003805460ff60a01b1916600160a01b17905550505050505050565b6000546001600160a01b03163314610deb5760405162461bcd60e51b815260040161069290614fa7565b610df48161321d565b50565b806001600160a01b031663f851a4406040518163ffffffff1660e01b815260040160206040518083038186803b158015610e3057600080fd5b505afa158015610e44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610e689190810190613d12565b6001600160a01b0316336001600160a01b031614610e985760405162461bcd60e51b815260040161069290615027565b806001600160a01b031663c1e803346040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610ed357600080fd5b505af1158015610ee7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f0b9190810190613fe5565b15610df45760405162461bcd60e51b815260040161069290614fb7565b604051610f3490614b95565b604051809103902081565b6004546001600160a01b031681565b6001546001600160a01b031681565b60066020526000908152604090205481565b6005546001600160a01b031681565b601560209081526000928352604080842090915290825290205481565b60096020526000908152604090205481565b600f602052600090815260409020546001600160a01b031681565b60135460ff1615610feb5760405162461bcd60e51b815260040161069290614e27565b610df433826132a2565b6002546001600160a01b031681565b6000546001600160a01b0316331461102e5760405162461bcd60e51b815260040161069290614fa7565b61103782613331565b61104081613331565b6005546004546001600160a01b03918216911681156110715760405162461bcd60e51b815260040161069290614ef7565b600580546001600160a01b038087166001600160a01b03199283161790925560048054928616929091169190911790556003805460ff60a01b1916600160a01b1790556040517f559f314bb90394a4a9ceb724f365b36a53587d894352c43d12901fd680101456906110ea908490849088908890614c2a565b60405180910390a150505050565b60006111048484612884565b6001600160a01b038085166000908152600a60209081526040808320878452825280832093861683529290522080545b600081118015611164575061116482600183038154811061115157fe5b9060005260206000209060020201613357565b156111a45761119982600183038154811061117b57fe5b6000918252602090912060029091020154849063ffffffff612d6416565b925060001901611134565b50509392505050565b60116020526000908152604090205463ffffffff1681565b60135460ff1681565b60004382106111ef5760405162461bcd60e51b815260040161069290614f07565b6001600160a01b03831660009081526011602052604090205463ffffffff168061121d5760009150506113d7565b6001600160a01b038416600090815260106020908152604080832063ffffffff600019860181168552925290912054168310611299576001600160a01b03841660009081526010602090815260408083206000199490940163ffffffff1683529290522054600160201b90046001600160601b031690506113d7565b6001600160a01b038416600090815260106020908152604080832083805290915290205463ffffffff168310156112d45760009150506113d7565b600060001982015b8163ffffffff168163ffffffff16111561139757600282820363ffffffff16048103611306613c85565b506001600160a01b038716600090815260106020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b03169181019190915290871415611372576020015194506113d79350505050565b805163ffffffff1687111561138957819350611390565b6001820392505b50506112dc565b506001600160a01b038516600090815260106020908152604080832063ffffffff909416835292905220546001600160601b03600160201b909104169150505b92915050565b600354600160a01b900460ff166114065760405162461bcd60e51b815260040161069290614f87565b6003805460ff60a01b1916905560135460ff16156114365760405162461bcd60e51b815260040161069290614e27565b6114408282612884565b6001600160a01b038216600090815260086020526040812080548390811061146457fe5b600091825260208083206001600160a01b038716808552600783526040808620888752845280862033808852908552818720928752600a85528187208988528552818720908752909352918420600590930201935091806114c5848461336c565b9092509050811515806114d85750600081115b6114f45760405162461bcd60e51b815260040161069290614fc7565b8115806114ff575080155b61151b5760405162461bcd60e51b815260040161069290614de7565b81156116345761152b87876128bb565b6000611571856001015461156564e8d4a510006115598a600301548a6000015461346390919063ffffffff16565b9063ffffffff61349d16565b9063ffffffff6134df16565b6004805460405163135b33cd60e31b81529293506001600160a01b031691639ad99e68916115a5918c913391879101614c02565b600060405180830381600087803b1580156115bf57600080fd5b505af11580156115d3573d6000803e3d6000fd5b505086546115ea925090508463ffffffff6134df16565b808655600387015461160d9164e8d4a5100091611559919063ffffffff61346316565b6001860155855461162e906001600160a01b0316338563ffffffff61352116565b506116b8565b8354611646908263ffffffff6134df16565b84556001600160a01b038716600090815260126020908152604080832089845290915290205461167c908263ffffffff6134df16565b6001600160a01b0380891660009081526012602090815260408083208b845290915290209190915585546116b89116338363ffffffff61352116565b856001600160a01b038816337fe31da05fae6db869f5ea51f4b638aa6884070b6c87f18f63bd2291a12cb2f5186116f5868663ffffffff612d6416565b6040516117029190614d0d565b60405180910390a450506003805460ff60a01b1916600160a01b1790555050505050565b600e6020526000908152604090205481565b6117766040518060400160405280601c81526020017f73657428616464726573732c75696e743235362c75696e7432353629000000008152506127e2565b6117808383612884565b61178983613543565b6001600160a01b038316600090815260086020526040812080549091906118029084906117f6908590889081106117bc57fe5b60009182526020808320600160059093020191909101546001600160a01b038b16835260099091526040909120549063ffffffff6134df16565b9063ffffffff612d6416565b9050600081116118245760405162461bcd60e51b815260040161069290615037565b600082858154811061183257fe5b90600052602060002090600502016001015490508383868154811061185357fe5b9060005260206000209060050201600101819055508160096000886001600160a01b03166001600160a01b031681526020019081526020016000208190555084866001600160a01b03167f6ee09c6cb801194690c195c69f465aaf7c80255cbeafaab9600f47ed79de2ca983876040516118ce929190615062565b60405180910390a3505050505050565b611906604051806040016040528060078152602001667061757365282960c81b8152506127e2565b60135460ff16156119295760405162461bcd60e51b815260040161069290614eb7565b6013805460ff1916600117905560405133907fdffada2889ebfab9224c24069d833f3de835d8cf99872d49e7b7ba5fccb7a46f90600090a2565b60135460ff16156119865760405162461bcd60e51b815260040161069290614e27565b6119908282612884565b61199a82826128bb565b5050565b600860205281600052604060002081815481106119b757fe5b6000918252602090912060059091020180546001820154600283015460038401546004909401546001600160a01b039093169550909350919085565b611a146040518060600160405280602881526020016152b1602891396127e2565b60048054604051633d6ac5b360e21b81526001600160a01b039091169163f5ab16cc91611a4391869101614bab565b60206040518083038186803b158015611a5b57600080fd5b505afa158015611a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250611a939190810190613f88565b611aaf5760405162461bcd60e51b815260040161069290614f97565b611ab882613543565b6001600160a01b0382166000818152600660205260409081902080549084905590519091907fad96cee0d692f0250b98e085504f399da6733854908215f6203fe3c69366d9f590611b0c9084908690615062565b60405180910390a2505050565b6000806000611b288686612884565b5050506001600160a01b03928316600090815260076020908152604080832094835293815283822092909416815292529020805460018201546002909201549092565b600354600160a01b900460ff16611b945760405162461bcd60e51b815260040161069290614f87565b6003805460ff60a01b1916905560135460ff1615611bc45760405162461bcd60e51b815260040161069290614e27565b611bce8282612884565b6001600160a01b0382166000908152600860205260408120805483908110611bf257fe5b600091825260208083206001600160a01b0380881685526007835260408086208887528452808620918a1686529252922060059091029091019150611c3784846128bb565b611c4284848761202d565b15611c5f5760405162461bcd60e51b815260040161069290614f37565b805415611ce3576000611c728284612a76565b90508015611ce157611c848284612da6565b6001830155611c94858783612a8a565b83856001600160a01b0316876001600160a01b03167f865ca08d59f5cb456e85cd2f7ef63664ea4f73327414e9d8152c4158b0e9464584604051611cd89190614d0d565b60405180910390a45b505b50506003805460ff60a01b1916600160a01b179055505050565b611d1e6040518060600160405280603381526020016152d9603391396127e2565b611d288383612884565b600081118015611d3b57506312cc030081105b611d575760405162461bcd60e51b815260040161069290614fd7565b6001600160a01b0383166000908152600860205260408120805484908110611d7b57fe5b9060005260206000209060050201905060008160040154905082826004018190555083856001600160a01b03167f0bcf80c5060ccf99b7a993c57a94b232fc2c5c04bd74c7c7d174595fee6bc31f8386604051611dd9929190615062565b60405180910390a35050505050565b6000611df48484612884565b6001600160a01b0384166000908152600860205260408120805485908110611e1857fe5b600091825260208083206001600160a01b03808a168086526007845260408087208b885285528087208a8416885285528087206003600590970290940195860154918752601285528087208b885290945283862054855494516370a0823160e01b8152959750929590949093611eef939216906370a0823190611e9f903090600401614bab565b60206040518083038186803b158015611eb757600080fd5b505afa158015611ecb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506115659190810190613fe5565b6001600160a01b0389166000908152600660205260409020546002860154919250439182118015611f1f57508215155b15611fb5576000611f3d8760020154846134df90919063ffffffff16565b6001600160a01b038c1660009081526009602052604081205460018a01549293509091611f85919061155990611f79868863ffffffff61346316565b9063ffffffff61346316565b9050611fb0611fa3866115598464e8d4a5100063ffffffff61346316565b879063ffffffff612d6416565b955050505b6001600160a01b03808b166000908152600a602090815260408083208d84528252808320938c16835292905290812090611fee82612f95565b91505061201d876001015461156564e8d4a510006115598a611f79878e600001546134df90919063ffffffff16565b9c9b505050505050505050505050565b6001600160a01b038084166000908152600a602090815260408083208684528252808320938516835292905290812061206581612f95565b5095945050505050565b6017546001600160a01b031681565b6047546001600160a01b031690565b6001600160a01b03811660009081526011602052604081205463ffffffff16806120b85760006120f7565b6001600160a01b0383166000908152601060209081526040808320600019850163ffffffff168452909152902054600160201b90046001600160601b03165b9150505b919050565b606061210c8484612884565b6001600160a01b038085166000908152600a602090815260408083208784528252808320938616835292815282822080548451818402810184019095528085529092909184015b828210156121ad5760008481526020908190206040805160608101825260028602909201805483526001908101546001600160801b0380821685870152600160801b90910416918301919091529083529092019101612153565b5050505090509392505050565b60146020526000908152604090205460ff1681565b60135460ff16156121f25760405162461bcd60e51b815260040161069290614e27565b600060405161220090614b95565b604080519182900382208282019091526008825267161594d5985d5b1d60c21b6020909201919091527fddfcc46608a8bd52ebf900f03a24cc97b73a6046cec8c5d0f74a211e376e967a612252613578565b306040516020016122669493929190614d29565b604051602081830303815290604052805190602001209050600060405161228c90614ba0565b6040519081900381206122a7918a908a908a90602001614d1b565b604051602081830303815290604052805190602001209050600082826040516020016122d4929190614b64565b60405160208183030381529060405280519060200120905060006122fa8288888861357c565b6001600160a01b0381166000908152600e60205260409020805460018101909155909150891461233c5760405162461bcd60e51b815260040161069290614e97565b8742111561235c5760405162461bcd60e51b815260040161069290614e77565b612366818b6132a2565b505050505b505050505050565b6001600160a01b031660009081526008602052604090205490565b6000546001600160a01b031633146123b85760405162461bcd60e51b815260040161069290614fa7565b6001600160a01b0383166123de5760405162461bcd60e51b815260040161069290614e87565b6001600160a01b0382166124045760405162461bcd60e51b815260040161069290614f17565b61240e8282612884565b6016546017546018546040516001600160a01b03808816948116937f8def9436d6e31b89ed00948ba91d0cb6936eada5154cb1b45b55683fb9e492379361245d93919092169188918890614c83565b60405180910390a3601680546001600160a01b039485166001600160a01b0319918216179091556017805493909416921691909117909155601855565b6003546001600160a01b031681565b604051610f3490614ba0565b60185481565b601060209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6312cc030081565b6000546001600160a01b031681565b6125286040518060600160405280602c8152602001615338602c91396127e2565b61253185613331565b61253a83613331565b6004546001600160a01b03166125625760405162461bcd60e51b815260040161069290614e07565b600084116125825760405162461bcd60e51b815260040161069290614fe7565b61258b85613543565b6001600160a01b0385166000908152600860205260408120805490915b8181101561260657856001600160a01b03168382815481106125c657fe5b60009182526020909120600590910201546001600160a01b031614156125fe5760405162461bcd60e51b815260040161069290614f77565b6001016125a8565b506001600160a01b03851660009081526014602052604090205460ff16156126405760405162461bcd60e51b815260040161069290614ee7565b6001600160a01b038716600090815260096020526040902054612669908763ffffffff612d6416565b6001600160a01b0388811660009081526009602090815260408083209490945560068152838220889055835160a0810185528984168082528183018c81524383880190815260608401868152608085018c81528b5460018082018e558d8a52888a209751600590920290970180546001600160a01b031916918b169190911781559351848701559151600284015551600383015551600491820155908452601490925291849020805460ff1916831790558054935163fb66fb4d60e01b8152939092169263fb66fb4d92612741928c92909101614cb8565b600060405180830381600087803b15801561275b57600080fd5b505af115801561276f573d6000803e3d6000fd5b50505050846001600160a01b03166001838054905003886001600160a01b03167fd7fa4bff1cd2253c0789c3291a786a6f6b1a3b4569a75af683a15d52abb6a0bf8988886040516127c293929190615070565b60405180910390a450505050505050565b6016546001600160a01b031681565b6047546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906128159033908690600401614bc7565b60206040518083038186803b15801561282d57600080fd5b505afa158015612841573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506128659190810190613f88565b90508061199a5760405162461bcd60e51b815260040161069290614e47565b6001600160a01b038216600090815260086020526040902054811061199a5760405162461bcd60e51b815260040161069290614df7565b6001600160a01b03821660009081526008602052604081208054839081106128df57fe5b9060005260206000209060050201905080600201544311612900575061199a565b80546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612930903090600401614bab565b60206040518083038186803b15801561294857600080fd5b505afa15801561295c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506129809190810190613fe5565b6001600160a01b03851660009081526012602090815260408083208784529091529020549091506129b890829063ffffffff6134df16565b9050806129cc57504360029091015561199a565b600282015443906000906129e790839063ffffffff6134df16565b6001600160a01b03871660009081526009602090815260408083205460018901546006909352908320549394509192612a30929161155991611f7990879063ffffffff61346316565b9050612a5f612a4e856115598464e8d4a5100063ffffffff61346316565b60038701549063ffffffff612d6416565b600386015550504360029093019290925550505050565b600061071183600101546115658585612da6565b600480546040516370a0823160e01b81526001600160a01b03918216926000928716916370a0823191612abf91869101614bab565b60206040518083038186803b158015612ad757600080fd5b505afa158015612aeb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250612b0f9190810190613fe5565b6001600160a01b038087166000908152601560209081526040808320938916835292905290812054919250612b4a858363ffffffff612d6416565b9050828111612c28578115612bbd576001600160a01b038088166000818152601560209081526040808320948b1680845294909152808220829055517f6bdfd5e51d01475945224d3d37965916fd8df699ef9e8888af4359aa8622216091612bb491879190615047565b60405180910390a35b60405163135b33cd60e31b81526001600160a01b03851690639ad99e6890612bed908a908a908690600401614c68565b600060405180830381600087803b158015612c0757600080fd5b505af1158015612c1b573d6000803e3d6000fd5b5050505050505050612cfe565b6001600160a01b038088166000818152601560209081526040808320948b168084529490915290819020868503908190559051909291907f6bdfd5e51d01475945224d3d37965916fd8df699ef9e8888af4359aa8622216090612c8e9087908690615062565b60405180910390a360405163135b33cd60e31b81526001600160a01b03861690639ad99e6890612cc6908b908b908990600401614c68565b600060405180830381600087803b158015612ce057600080fd5b505af1158015612cf4573d6000803e3d6000fd5b5050505050505050505b505050565b604051612d5e9085906323b872dd60e01b90612d2790879087908790602401614c68565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526135a6565b50505050565b600061071183836040518060400160405280601b81526020017f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525061368b565b600061071164e8d4a510006115598460030154611f79876002015488600001546134df90919063ffffffff16565b600081600160601b8410612dfb5760405162461bcd60e51b81526004016106929190614dc6565b509192915050565b816001600160a01b0316836001600160a01b031614158015612e2e57506000816001600160601b0316115b15612cfe576001600160a01b03831615612ee6576001600160a01b03831660009081526011602052604081205463ffffffff169081612e6e576000612ead565b6001600160a01b0385166000908152601060209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b90506000612ed482856040518060600160405280602c815260200161530c602c91396136bb565b9050612ee2868484846136fa565b5050505b6001600160a01b03821615612cfe576001600160a01b03821660009081526011602052604081205463ffffffff169081612f21576000612f60565b6001600160a01b0384166000908152601060209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b90506000612f8782856040518060600160405280602b81526020016151da602b91396138af565b905061236b858484846136fa565b805460009081905b801561303357836001820381548110612fb257fe5b6000918252602090912060016002909202018101546001600160801b03600160801b9091041614156130155761300e846001830381548110612ff057fe5b6000918252602090912060029091020154839063ffffffff612d6416565b915061302a565b61302784600183038154811061117b57fe5b92505b60001901612f9d565b50915091565b8254604080516060810182526000808252602080830182815260019484018581528587018a5589845291909220925160028602909301928355905191909201805492516001600160801b03908116600160801b029281166001600160801b0319909416939093179092161790555b6000811180156130e25750818460018303815481106130c257fe5b60009182526020909120600160029092020101546001600160801b031611155b15613169578360018203815481106130f657fe5b906000526020600020906002020184828154811061311057fe5b600091825260209091208254600290920201908155600191820180549290910180546001600160801b0319166001600160801b03938416178082559154600160801b9081900484160291909216179055600019016130a7565b6040518060600160405280848152602001613183846138e2565b6001600160801b0316815260200160016001600160801b03168152508482815481106131ab57fe5b60009182526020918290208351600292830290910190815591830151600190920180546040909401516001600160801b03199094166001600160801b03938416178316600160801b939094169290920292909217905585015461320e9084612d64565b85600201819055505050505050565b6001600160a01b0381166132435760405162461bcd60e51b815260040161069290614ec7565b604780546001600160a01b038381166001600160a01b03198316179092556040519116907f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0906132969083908590614be7565b60405180910390a15050565b6001600160a01b038083166000908152600f6020526040812054909116906132c98461390b565b6001600160a01b038581166000818152600f602052604080822080546001600160a01b031916898616908117909155905194955093928616927f0cc323ffec3ea49cbcddc0de1480978126d350c6a45dff33ad2f1cda6ae992619190a4612d5e828483612e03565b6001600160a01b038116610df45760405162461bcd60e51b815260040161069290614f27565b60010154426001600160801b03909116111590565b805460009081905b600081118015613391575061339184600183038154811061115157fe5b15613432578360018203815481106133a557fe5b6000918252602090912060016002909202018101546001600160801b03600160801b9091041614156133ea576133e3846001830381548110612ff057fe5b91506133ff565b6133fc84600183038154811061117b57fe5b92505b8380548061340957fe5b600082815260208120600019928301600281029091018281556001019190915590915501613374565b50613457613446828463ffffffff612d6416565b60028601549063ffffffff6134df16565b60028501559250929050565b600082613472575060006113d7565b8282028284828161347f57fe5b04146107115760405162461bcd60e51b815260040161069290614f67565b600061071183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613a21565b600061071183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613a58565b604051612cfe90849063a9059cbb60e01b90612d279086908690602401614cd3565b6001600160a01b038116600090815260086020526040812054905b81811015612cfe5761357083826128bb565b60010161355e565b4690565b600080600061358d87878787613a7c565b9150915061359a81613b5c565b5090505b949350505050565b6135b8826001600160a01b0316613c25565b6135d45760405162461bcd60e51b815260040161069290615007565b60006060836001600160a01b0316836040516135f09190614b58565b6000604051808303816000865af19150503d806000811461362d576040519150601f19603f3d011682016040523d82523d6000602084013e613632565b606091505b5091509150816136545760405162461bcd60e51b815260040161069290614ff7565b805115612d5e578080602001905161366f9190810190613f88565b612d5e5760405162461bcd60e51b815260040161069290614e67565b600083830182858210156136b25760405162461bcd60e51b81526004016106929190614dc6565b50949350505050565b6000836001600160601b0316836001600160601b0316111582906136f25760405162461bcd60e51b81526004016106929190614dc6565b505050900390565b600061371e4360405180606001604052806038815260200161527960389139613c5e565b905060008463ffffffff1611801561376757506001600160a01b038516600090815260106020908152604080832063ffffffff6000198901811685529252909120548282169116145b156137c6576001600160a01b0385166000908152601060209081526040808320600019880163ffffffff168452909152902080546fffffffffffffffffffffffff000000001916600160201b6001600160601b03851602179055613865565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000818152601083528781208c871682528352878120965187549451909516600160201b026fffffffffffffffffffffffff000000001995871663ffffffff19958616179590951694909417909555938252601190935292909220805460018801909316929091169190911790555b846001600160a01b03167f6adb589fed1e8542fb7a6b10f00a85e02265e77f9ae3ca8ff93b22983e1af9a084846040516138a09291906150c2565b60405180910390a25050505050565b6000838301826001600160601b0380871690831610156136b25760405162461bcd60e51b81526004016106929190614dc6565b6000600160801b82106139075760405162461bcd60e51b815260040161069290614ea7565b5090565b6005546000906001600160a01b03166139365760405162461bcd60e51b815260040161069290614e57565b6005546001600160a01b03166000908152600860205260408120805490915b81811015613a165760055483546001600160a01b039091169084908390811061397a57fe5b60009182526020909120600590910201546001600160a01b03161415613a0e576005546001600160a01b039081166000908152600760209081526040808320858452825280832093891683529290522060028101548154613a03916139e5919063ffffffff6134df16565b60405180606001604052806028815260200161523060289139612dd4565b9450505050506120fb565b600101613955565b506000949350505050565b60008183613a425760405162461bcd60e51b81526004016106929190614dc6565b506000838581613a4e57fe5b0495945050505050565b600081848411156136f25760405162461bcd60e51b81526004016106929190614dc6565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115613ab35750600090506003613b53565b8460ff16601b14158015613acb57508460ff16601c14155b15613adc5750600090506004613b53565b600060018787878760405160008152602001604052604051613b019493929190614d51565b6020604051602081039080840390855afa158015613b23573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116613b4c57506000915060019050613b53565b9150600090505b94509492505050565b6000816004811115613b6a57fe5b1415613b7557610df4565b6001816004811115613b8357fe5b1415613ba15760405162461bcd60e51b815260040161069290614dd7565b6002816004811115613baf57fe5b1415613bcd5760405162461bcd60e51b815260040161069290614e17565b6003816004811115613bdb57fe5b1415613bf95760405162461bcd60e51b815260040161069290614ed7565b6004816004811115613c0757fe5b1415610df45760405162461bcd60e51b815260040161069290614f47565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061359e575050151592915050565b600081600160201b8410612dfb5760405162461bcd60e51b81526004016106929190614dc6565b604080518082019091526000808252602082015290565b80356113d781615198565b80516113d781615198565b80516113d7816151ac565b80356113d7816151b5565b80356113d7816151be565b80516113d7816151b5565b80356113d7816151c7565b80356113d7816151d0565b600060208284031215613d0657600080fd5b600061359e8484613c9c565b600060208284031215613d2457600080fd5b600061359e8484613ca7565b60008060408385031215613d4357600080fd5b6000613d4f8585613c9c565b9250506020613d6085828601613c9c565b9150509250929050565b600080600060608486031215613d7f57600080fd5b6000613d8b8686613c9c565b9350506020613d9c86828701613c9c565b9250506040613dad86828701613cbd565b9150509250925092565b60008060408385031215613dca57600080fd5b6000613dd68585613c9c565b9250506020613d6085828601613cbd565b600080600060608486031215613dfc57600080fd5b6000613e088686613c9c565b9350506020613e1986828701613cbd565b9250506040613dad86828701613c9c565b600080600080600060a08688031215613e4257600080fd5b6000613e4e8888613c9c565b9550506020613e5f88828901613cbd565b9450506040613e7088828901613cc8565b9350506060613e8188828901613cbd565b9250506080613e9288828901613cbd565b9150509295509295909350565b600080600060608486031215613eb457600080fd5b6000613ec08686613c9c565b9350506020613d9c86828701613cbd565b60008060008060008060c08789031215613eea57600080fd5b6000613ef68989613c9c565b9650506020613f0789828a01613cbd565b9550506040613f1889828a01613cbd565b9450506060613f2989828a01613ce9565b9350506080613f3a89828a01613cbd565b92505060a0613f4b89828a01613cbd565b9150509295509295509295565b60008060408385031215613f6b57600080fd5b6000613f778585613c9c565b9250506020613d6085828601613cde565b600060208284031215613f9a57600080fd5b600061359e8484613cb2565b600080600060608486031215613fbb57600080fd5b6000613d8b8686613cc8565b600060208284031215613fd957600080fd5b600061359e8484613cc8565b600060208284031215613ff757600080fd5b600061359e8484613cd3565b600061400f8383614af8565b505060600190565b61402081615141565b82525050565b614020816150f0565b600061403a826150e3565b61404481856150e7565b935061404f836150dd565b8060005b8381101561407d5781516140678882614003565b9750614072836150dd565b925050600101614053565b509495945050505050565b614020816150fb565b61402081615100565b6140206140a682615100565b615100565b60006140b6826150e3565b6140c081856120fb565b93506140d0818560208601615162565b9290920192915050565b61402081615103565b6140208161514c565b60006140f7826150e3565b61410181856150e7565b9350614111818560208601615162565b61411a8161518e565b9093019392505050565b60006141316018836150e7565b7f45434453413a20696e76616c6964207369676e61747572650000000000000000815260200192915050565b600061416a6012836150e7565b71696e636f6e73697374656e7420737461746560701b815260200192915050565b60006141986013836150e7565b727661756c743a20706f6f6c206578697374733f60681b815260200192915050565b60006141c7601f836150e7565b7f53746f726520636f6e7472616374206164647265737320697320656d70747900815260200192915050565b6000614200601f836150e7565b7f45434453413a20696e76616c6964207369676e6174757265206c656e67746800815260200192915050565b6000614239600f836150e7565b6e15985d5b1d081a5cc81c185d5cd959608a1b815260200192915050565b60006142646013836150e7565b7215985d5b1d081a5cc81b9bdd081c185d5cd959606a1b815260200192915050565b6000614293600c836150e7565b6b155b985d5d1a1bdc9a5e995960a21b815260200192915050565b60006142bb6030836150e7565b7f5856535661756c743a3a6765745374616b65416d6f756e743a2078767320616481526f191c995cdcc81a5cc81b9bdd081cd95d60821b602082015260400192915050565b600061430d602a836150e7565b7f5361666542455032303a204245503230206f7065726174696f6e20646964206e8152691bdd081cdd58d8d9595960b21b602082015260400192915050565b6000614359602a836150e7565b7f5856535661756c743a3a64656c656761746542795369673a207369676e6174758152691c9948195e1c1a5c995960b21b602082015260400192915050565b60006143a56022836150e7565b7f7072696d6520746f6b656e2063616e6e6f74206265207a65726f206164647265815261737360f01b602082015260400192915050565b60006143e96026836150e7565b7f5856535661756c743a3a64656c656761746542795369673a20696e76616c6964815265206e6f6e636560d01b602082015260400192915050565b60006144316002836120fb565b61190160f01b815260020192915050565b600061444f6027836150e7565b7f53616665436173743a2076616c756520646f65736e27742066697420696e20318152663238206269747360c81b602082015260400192915050565b60006144986017836150e7565b7f5661756c7420697320616c726561647920706175736564000000000000000000815260200192915050565b60006144d16025836150e7565b7f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164815264647265737360d81b602082015260400192915050565b60006145186022836150e7565b7f45434453413a20696e76616c6964207369676e6174757265202773272076616c815261756560f01b602082015260400192915050565b600061455c601a836150e7565b7f546f6b656e2065786973747320696e206f7468657220706f6f6c000000000000815260200192915050565b60006145956013836150e7565b72185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b815260200192915050565b60006145c4602b836150e7565b7f5856535661756c743a3a6765745072696f72566f7465733a206e6f742079657481526a0819195d195c9b5a5b995960aa1b602082015260400192915050565b6000614611601d836150e7565b7f7265776172642063616e6e6f74206265207a65726f2061646472657373000000815260200192915050565b600061464a6018836150e7565b7f7a65726f2061646472657373206e6f7420616c6c6f7765640000000000000000815260200192915050565b6000614683601a836150e7565b7f657865637574652070656e64696e67207769746864726177616c000000000000815260200192915050565b60006146bc6022836150e7565b7f45434453413a20696e76616c6964207369676e6174757265202776272076616c815261756560f01b602082015260400192915050565b60006147006043836120fb565b7f454950373132446f6d61696e28737472696e67206e616d652c75696e7432353681527f20636861696e49642c6164647265737320766572696679696e67436f6e74726160208201526263742960e81b604082015260430192915050565b600061476b601f836150e7565b7f72657175657374656420616d6f756e742063616e6e6f74206265207a65726f00815260200192915050565b60006147a46021836150e7565b7f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f8152607760f81b602082015260400192915050565b60006147e76012836150e7565b71141bdbdb08185b1c9958591e48185919195960721b815260200192915050565b6000614815600a836150e7565b691c994b595b9d195c995960b21b815260200192915050565b600061483b6014836150e7565b7324b73b30b634b2103932bbb0b932103a37b5b2b760611b815260200192915050565b600061486b600e836150e7565b6d37b7363c9030b236b4b71031b0b760911b815260200192915050565b60006148956015836150e7565b7418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b815260200192915050565b60006148c66013836150e7565b726e6f7468696e6720746f20776974686472617760681b815260200192915050565b60006148f5601a836150e7565b7f496e76616c6964206e6577206c6f636b696e6720706572696f64000000000000815260200192915050565b600061492e601d836150e7565b7f416c6c6f6320706f696e7473206d757374206e6f74206265207a65726f000000815260200192915050565b60006149676020836150e7565b7f5361666542455032303a206c6f772d6c6576656c2063616c6c206661696c6564815260200192915050565b60006149a0603a836120fb565b7f44656c65676174696f6e28616464726573732064656c6567617465652c75696e81527f74323536206e6f6e63652c75696e7432353620657870697279290000000000006020820152603a0192915050565b60006149ff601f836150e7565b7f5361666542455032303a2063616c6c20746f206e6f6e2d636f6e747261637400815260200192915050565b6000614a38601b836150e7565b7f72657175657374656420616d6f756e7420697320696e76616c69640000000000815260200192915050565b6000614a716022836150e7565b7f6f6e6c792070726f78792061646d696e2063616e206368616e676520627261698152616e7360f01b602082015260400192915050565b6000614ab5602e836150e7565b7f416c6c6f6320706f696e7473207065722072657761726420746f6b656e206d7581526d7374206e6f74206265207a65726f60901b602082015260400192915050565b80516060830190614b098482614091565b506020820151614b1c6020850182614b2b565b506040820151612d5e60408501825b6140208161510e565b61402081615126565b6140208161512f565b61402081615157565b61402081615135565b600061071182846140ab565b6000614b6f82614424565b9150614b7b828561409a565b602082019150614b8b828461409a565b5060200192915050565b60006113d7826146f3565b60006113d782614993565b602081016113d78284614026565b602081016113d78284614017565b60408101614bd58285614017565b818103602083015261359e81846140ec565b60408101614bf58285614026565b6107116020830184614026565b60608101614c108286614026565b614c1d6020830185614017565b61359e6040830184614091565b60808101614c388287614026565b614c456020830186614026565b614c526040830185614026565b614c5f6060830184614026565b95945050505050565b60608101614c768286614026565b614c1d6020830185614026565b60808101614c918287614026565b614c9e6020830186614026565b614cab6040830185614091565b614c5f6060830184614091565b60408101614cc68285614026565b6107116020830184614088565b60408101614ce18285614026565b6107116020830184614091565b60208082528101610711818461402f565b602081016113d78284614088565b602081016113d78284614091565b60808101614c918287614091565b60808101614d378287614091565b614d446020830186614091565b614c526040830185614091565b60808101614d5f8287614091565b614c9e6020830186614b3d565b602081016113d782846140da565b60a08101614d8882886140da565b614d956020830187614091565b614da26040830186614091565b614daf6060830185614091565b614dbc6080830184614091565b9695505050505050565b6020808252810161071181846140ec565b602080825281016113d781614124565b602080825281016113d78161415d565b602080825281016113d78161418b565b602080825281016113d7816141ba565b602080825281016113d7816141f3565b602080825281016113d78161422c565b602080825281016113d781614257565b602080825281016113d781614286565b602080825281016113d7816142ae565b602080825281016113d781614300565b602080825281016113d78161434c565b602080825281016113d781614398565b602080825281016113d7816143dc565b602080825281016113d781614442565b602080825281016113d78161448b565b602080825281016113d7816144c4565b602080825281016113d78161450b565b602080825281016113d78161454f565b602080825281016113d781614588565b602080825281016113d7816145b7565b602080825281016113d781614604565b602080825281016113d78161463d565b602080825281016113d781614676565b602080825281016113d7816146af565b602080825281016113d78161475e565b602080825281016113d781614797565b602080825281016113d7816147da565b602080825281016113d781614808565b602080825281016113d78161482e565b602080825281016113d78161485e565b602080825281016113d781614888565b602080825281016113d7816148b9565b602080825281016113d7816148e8565b602080825281016113d781614921565b602080825281016113d78161495a565b602080825281016113d7816149f2565b602080825281016113d781614a2b565b602080825281016113d781614a64565b602080825281016113d781614aa8565b604081016150558285614091565b61071160208301846140e3565b60408101614ce18285614091565b6060810161507e8286614091565b614c1d6020830185614091565b602081016113d78284614b34565b604081016150a78285614b34565b6107116020830184614b4f565b602081016113d78284614b4f565b604081016150d08285614b46565b6107116020830184614b46565b60200190565b5190565b90815260200190565b60006113d78261511a565b151590565b90565b60006113d7826150f0565b6001600160801b031690565b6001600160a01b031690565b63ffffffff1690565b60ff1690565b6001600160601b031690565b60006113d782615103565b60006113d782615100565b60006113d782615135565b60005b8381101561517d578181015183820152602001615165565b83811115612d5e5750506000910152565b601f01601f191690565b6151a1816150f0565b8114610df457600080fd5b6151a1816150fb565b6151a181615100565b6151a181615103565b6151a181615126565b6151a18161512f56fe5856535661756c743a3a5f6d6f7665566f7465733a20766f746520616d6f756e74206f766572666c6f77735856535661756c743a3a726571756573745769746864726177616c3a20766f746573206f766572666c6f775856535661756c743a3a6765745374616b65416d6f756e743a20766f746573206f766572666c6f775856535661756c743a3a6465706f7369743a20766f746573206f766572666c6f775856535661756c743a3a5f7772697465436865636b706f696e743a20626c6f636b206e756d62657220657863656564732033322062697473736574526577617264416d6f756e74506572426c6f636b28616464726573732c75696e74323536297365745769746864726177616c4c6f636b696e67506572696f6428616464726573732c75696e743235362c75696e74323536295856535661756c743a3a5f6d6f7665566f7465733a20766f746520616d6f756e7420756e646572666c6f777361646428616464726573732c75696e743235362c616464726573732c75696e743235362c75696e7432353629a365627a7a723158206fcd6577817fe07166c8f22ad5e6c4a8771a4690f6356182a14a0bf96f9a45af6c6578706572696d656e74616cf564736f6c63430005100040", + "devdoc": { + "author": "Venus", + "methods": { + "add(address,uint256,address,uint256,uint256)": { + "details": "This vault DOES NOT support deflationary tokens — it expects that the amount of transferred tokens would equal the actually deposited amount. In practice this means that this vault DOES NOT support USDT and similar tokens (that do not provide these guarantees).", + "params": { + "_allocPoint": "Number of allocation points assigned to this pool", + "_lockPeriod": "A period between withdrawal request and a moment when it's executable", + "_rewardPerBlock": "Initial reward per block, in terms of _rewardToken", + "_rewardToken": "Reward token address", + "_token": "Staked token" + } + }, + "claim(address,address,uint256)": { + "params": { + "_account": "The account for which to claim rewards", + "_pid": "The Pool Index", + "_rewardToken": "The Reward Token Address" + } + }, + "delegate(address)": { + "params": { + "delegatee": "The address to delegate votes to" + } + }, + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": { + "params": { + "delegatee": "The address to delegate votes to", + "expiry": "The time at which to expire the signature", + "nonce": "The contract state required to match the signature", + "r": "Half of the ECDSA signature pair", + "s": "Half of the ECDSA signature pair", + "v": "The recovery byte of the signature" + } + }, + "deposit(address,uint256,uint256)": { + "params": { + "_amount": "The amount to deposit to vault", + "_pid": "The Pool Index", + "_rewardToken": "The Reward Token Address" + } + }, + "executeWithdrawal(address,uint256)": { + "params": { + "_pid": "The Pool Index", + "_rewardToken": "The Reward Token Address" + } + }, + "getCurrentVotes(address)": { + "params": { + "account": "The address to get votes balance" + }, + "return": "The number of current votes for `account`" + }, + "getEligibleWithdrawalAmount(address,uint256,address)": { + "params": { + "_pid": "The Pool Index", + "_rewardToken": "The Reward Token Address", + "_user": "The User Address" + }, + "return": "withdrawalAmount Amount that the user can withdraw" + }, + "getPriorVotes(address,uint256)": { + "params": { + "account": "The address of the account to check", + "blockNumber": "The block number to get the vote balance at" + }, + "return": "The balance that user staked" + }, + "getRequestedAmount(address,uint256,address)": { + "params": { + "_pid": "The Pool Index", + "_rewardToken": "The Reward Token Address", + "_user": "The User Address" + }, + "return": "Total amount of requested but not yet executed withdrawals (including both executable and locked ones)" + }, + "getUserInfo(address,uint256,address)": { + "params": { + "_pid": "Pool index", + "_rewardToken": "Reward token address", + "_user": "User address" + }, + "return": "amount Deposited amountrewardDebt Reward debt (technical value used to track past payouts)pendingWithdrawals Requested but not yet executed withdrawals" + }, + "getWithdrawalRequests(address,uint256,address)": { + "params": { + "_pid": "The Pool Index", + "_rewardToken": "The Reward Token Address", + "_user": "The User Address" + }, + "return": "An array of withdrawal requests" + }, + "pendingReward(address,uint256,address)": { + "params": { + "_pid": "Pool index", + "_rewardToken": "Reward token address", + "_user": "User address" + }, + "return": "Reward the user is eligible for in this pool, in terms of _rewardToken" + }, + "pendingWithdrawalsBeforeUpgrade(address,uint256,address)": { + "params": { + "_pid": "The Pool Index", + "_rewardToken": "The Reward Token Address", + "_user": "The address of the user" + }, + "return": "beforeUpgradeWithdrawalAmount Total pending withdrawal amount in requests made before the vault upgrade" + }, + "poolLength(address)": { + "params": { + "rewardToken": "Reward token address" + }, + "return": "Number of pools that distribute the specified token as a reward" + }, + "requestWithdrawal(address,uint256,uint256)": { + "params": { + "_amount": "The amount to withdraw from the vault", + "_pid": "The Pool Index", + "_rewardToken": "The Reward Token Address" + } + }, + "set(address,uint256,uint256)": { + "params": { + "_allocPoint": "Number of allocation points assigned to this pool", + "_pid": "Pool index", + "_rewardToken": "Reward token address" + } + }, + "setAccessControl(address)": { + "details": "Admin function to set the access control address", + "params": { + "newAccessControlAddress": "New address for the access control" + } + }, + "setPrimeToken(address,address,uint256)": { + "params": { + "_primePoolId": "pool id for reward", + "_primeRewardToken": "address of reward token", + "_primeToken": "address of the prime token contract" + } + }, + "setRewardAmountPerBlock(address,uint256)": { + "params": { + "_rewardAmount": "Number of allocation points assigned to this pool", + "_rewardToken": "Reward token address" + } + }, + "setWithdrawalLockingPeriod(address,uint256,uint256)": { + "params": { + "_newPeriod": "New lock period", + "_pid": "Pool index", + "_rewardToken": "Reward token address" + } + }, + "updatePool(address,uint256)": { + "params": { + "_pid": "Pool index", + "_rewardToken": "Reward token address" + } + } + }, + "title": "XVS Vault" + }, + "userdoc": { + "methods": { + "_become(address)": { + "notice": "* Admin Functions **" + }, + "accessControlManager()": { + "notice": "Returns the address of the access control manager contract" + }, + "add(address,uint256,address,uint256,uint256)": { + "notice": "Add a new token pool" + }, + "claim(address,address,uint256)": { + "notice": "Claim rewards for pool" + }, + "delegate(address)": { + "notice": "Delegate votes from `msg.sender` to `delegatee`" + }, + "delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32)": { + "notice": "Delegates votes from signatory to `delegatee`" + }, + "deposit(address,uint256,uint256)": { + "notice": "Deposit XVSVault for XVS allocation" + }, + "executeWithdrawal(address,uint256)": { + "notice": "Execute withdrawal to XVSVault for XVS allocation" + }, + "getCurrentVotes(address)": { + "notice": "Gets the current votes balance for `account`" + }, + "getEligibleWithdrawalAmount(address,uint256,address)": { + "notice": "Get unlocked withdrawal amount" + }, + "getPriorVotes(address,uint256)": { + "notice": "Determine the xvs stake balance for an account" + }, + "getRequestedAmount(address,uint256,address)": { + "notice": "Get requested amount" + }, + "getUserInfo(address,uint256,address)": { + "notice": "Get user info with reward token address and pid" + }, + "getWithdrawalRequests(address,uint256,address)": { + "notice": "Returns the array of withdrawal requests that have not been executed yet" + }, + "pause()": { + "notice": "Pauses vault" + }, + "pendingReward(address,uint256,address)": { + "notice": "View function to see pending XVSs on frontend" + }, + "pendingWithdrawalsBeforeUpgrade(address,uint256,address)": { + "notice": "Gets the total pending withdrawal amount of a user before upgrade" + }, + "poolLength(address)": { + "notice": "Returns the number of pools with the specified reward token" + }, + "requestWithdrawal(address,uint256,uint256)": { + "notice": "Request withdrawal to XVSVault for XVS allocation" + }, + "resume()": { + "notice": "Resume vault" + }, + "set(address,uint256,uint256)": { + "notice": "Update the given pool's reward allocation point" + }, + "setAccessControl(address)": { + "notice": "Sets the address of the access control of this contract" + }, + "setPrimeToken(address,address,uint256)": { + "notice": "Sets the address of the prime token contract" + }, + "setRewardAmountPerBlock(address,uint256)": { + "notice": "Update the given reward token's amount per block" + }, + "setWithdrawalLockingPeriod(address,uint256,uint256)": { + "notice": "Update the lock period after which a requested withdrawal can be executed" + }, + "updatePool(address,uint256)": { + "notice": "Update reward variables of the given pool to be up-to-date" + } + }, + "notice": "The XVS Vault allows XVS holders to lock their XVS to recieve voting rights in Venus governance and are rewarded with XVS." + }, + "storageLayout": { + "storage": [ + { + "astId": 33645, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 33647, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "pendingAdmin", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 33649, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "implementation", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 33651, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "pendingXVSVaultImplementation", + "offset": 0, + "slot": "3", + "type": "t_address" + }, + { + "astId": 33656, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "_notEntered", + "offset": 20, + "slot": "3", + "type": "t_bool" + }, + { + "astId": 33658, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "xvsStore", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 33660, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "xvsAddress", + "offset": 0, + "slot": "5", + "type": "t_address" + }, + { + "astId": 33664, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "rewardTokenAmountsPerBlock", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 33697, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "userInfos", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_mapping(t_address,t_struct(UserInfo)33671_storage)))" + }, + { + "astId": 33702, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "poolInfos", + "offset": 0, + "slot": "8", + "type": "t_mapping(t_address,t_array(t_struct(PoolInfo)33682_storage)dyn_storage)" + }, + { + "astId": 33706, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "totalAllocPoints", + "offset": 0, + "slot": "9", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 33715, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "withdrawalRequests", + "offset": 0, + "slot": "10", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_mapping(t_address,t_array(t_struct(WithdrawalRequest)33689_storage)dyn_storage)))" + }, + { + "astId": 33719, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "__oldDelegatesSlot", + "offset": 0, + "slot": "11", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 33730, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "__oldCheckpointsSlot", + "offset": 0, + "slot": "12", + "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)33724_storage))" + }, + { + "astId": 33734, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "__oldNumCheckpointsSlot", + "offset": 0, + "slot": "13", + "type": "t_mapping(t_address,t_uint32)" + }, + { + "astId": 33738, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "nonces", + "offset": 0, + "slot": "14", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 33755, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "delegates", + "offset": 0, + "slot": "15", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 33761, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "checkpoints", + "offset": 0, + "slot": "16", + "type": "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)33724_storage))" + }, + { + "astId": 33765, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "numCheckpoints", + "offset": 0, + "slot": "17", + "type": "t_mapping(t_address,t_uint32)" + }, + { + "astId": 33771, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "totalPendingWithdrawals", + "offset": 0, + "slot": "18", + "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))" + }, + { + "astId": 33773, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "vaultPaused", + "offset": 0, + "slot": "19", + "type": "t_bool" + }, + { + "astId": 33777, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "isStakedToken", + "offset": 0, + "slot": "20", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 33783, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "pendingRewardTransfers", + "offset": 0, + "slot": "21", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 33785, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "primeToken", + "offset": 0, + "slot": "22", + "type": "t_contract(IPrime)11916" + }, + { + "astId": 33787, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "primeRewardToken", + "offset": 0, + "slot": "23", + "type": "t_address" + }, + { + "astId": 33789, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "primePoolId", + "offset": 0, + "slot": "24", + "type": "t_uint256" + }, + { + "astId": 33793, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "__gap", + "offset": 0, + "slot": "25", + "type": "t_array(t_uint256)46_storage" + }, + { + "astId": 4, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "_accessControlManager", + "offset": 0, + "slot": "71", + "type": "t_contract(IAccessControlManagerV5)1933" + }, + { + "astId": 8, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "__gap", + "offset": 0, + "slot": "72", + "type": "t_array(t_uint256)49_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_struct(PoolInfo)33682_storage)dyn_storage": { + "base": "t_struct(PoolInfo)33682_storage", + "encoding": "dynamic_array", + "label": "struct XVSVaultStorageV1.PoolInfo[]", + "numberOfBytes": "32" + }, + "t_array(t_struct(WithdrawalRequest)33689_storage)dyn_storage": { + "base": "t_struct(WithdrawalRequest)33689_storage", + "encoding": "dynamic_array", + "label": "struct XVSVaultStorageV1.WithdrawalRequest[]", + "numberOfBytes": "32" + }, + "t_array(t_uint256)46_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[46]", + "numberOfBytes": "1472" + }, + "t_array(t_uint256)49_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IAccessControlManagerV5)1933": { + "encoding": "inplace", + "label": "contract IAccessControlManagerV5", + "numberOfBytes": "20" + }, + "t_contract(IBEP20)26967": { + "encoding": "inplace", + "label": "contract IBEP20", + "numberOfBytes": "20" + }, + "t_contract(IPrime)11916": { + "encoding": "inplace", + "label": "contract IPrime", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_address,t_array(t_struct(PoolInfo)33682_storage)dyn_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct XVSVaultStorageV1.PoolInfo[])", + "numberOfBytes": "32", + "value": "t_array(t_struct(PoolInfo)33682_storage)dyn_storage" + }, + "t_mapping(t_address,t_array(t_struct(WithdrawalRequest)33689_storage)dyn_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct XVSVaultStorageV1.WithdrawalRequest[])", + "numberOfBytes": "32", + "value": "t_array(t_struct(WithdrawalRequest)33689_storage)dyn_storage" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_mapping(t_address,t_array(t_struct(WithdrawalRequest)33689_storage)dyn_storage)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint256 => mapping(address => struct XVSVaultStorageV1.WithdrawalRequest[])))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_mapping(t_address,t_array(t_struct(WithdrawalRequest)33689_storage)dyn_storage))" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_mapping(t_address,t_struct(UserInfo)33671_storage)))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint256 => mapping(address => struct XVSVaultStorageV1.UserInfo)))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_mapping(t_address,t_struct(UserInfo)33671_storage))" + }, + "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint256 => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint256,t_uint256)" + }, + "t_mapping(t_address,t_mapping(t_uint32,t_struct(Checkpoint)33724_storage))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(uint32 => struct XVSVaultStorageV1.Checkpoint))", + "numberOfBytes": "32", + "value": "t_mapping(t_uint32,t_struct(Checkpoint)33724_storage)" + }, + "t_mapping(t_address,t_struct(UserInfo)33671_storage)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => struct XVSVaultStorageV1.UserInfo)", + "numberOfBytes": "32", + "value": "t_struct(UserInfo)33671_storage" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_address,t_uint32)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint32)", + "numberOfBytes": "32", + "value": "t_uint32" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_array(t_struct(WithdrawalRequest)33689_storage)dyn_storage))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => struct XVSVaultStorageV1.WithdrawalRequest[]))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_array(t_struct(WithdrawalRequest)33689_storage)dyn_storage)" + }, + "t_mapping(t_uint256,t_mapping(t_address,t_struct(UserInfo)33671_storage))": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => mapping(address => struct XVSVaultStorageV1.UserInfo))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_struct(UserInfo)33671_storage)" + }, + "t_mapping(t_uint256,t_uint256)": { + "encoding": "mapping", + "key": "t_uint256", + "label": "mapping(uint256 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_uint32,t_struct(Checkpoint)33724_storage)": { + "encoding": "mapping", + "key": "t_uint32", + "label": "mapping(uint32 => struct XVSVaultStorageV1.Checkpoint)", + "numberOfBytes": "32", + "value": "t_struct(Checkpoint)33724_storage" + }, + "t_struct(Checkpoint)33724_storage": { + "encoding": "inplace", + "label": "struct XVSVaultStorageV1.Checkpoint", + "members": [ + { + "astId": 33721, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "fromBlock", + "offset": 0, + "slot": "0", + "type": "t_uint32" + }, + { + "astId": 33723, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "votes", + "offset": 4, + "slot": "0", + "type": "t_uint96" + } + ], + "numberOfBytes": "32" + }, + "t_struct(PoolInfo)33682_storage": { + "encoding": "inplace", + "label": "struct XVSVaultStorageV1.PoolInfo", + "members": [ + { + "astId": 33673, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "token", + "offset": 0, + "slot": "0", + "type": "t_contract(IBEP20)26967" + }, + { + "astId": 33675, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "allocPoint", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 33677, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "lastRewardBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 33679, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "accRewardPerShare", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 33681, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "lockPeriod", + "offset": 0, + "slot": "4", + "type": "t_uint256" + } + ], + "numberOfBytes": "160" + }, + "t_struct(UserInfo)33671_storage": { + "encoding": "inplace", + "label": "struct XVSVaultStorageV1.UserInfo", + "members": [ + { + "astId": 33666, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "amount", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 33668, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "rewardDebt", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 33670, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "pendingWithdrawals", + "offset": 0, + "slot": "2", + "type": "t_uint256" + } + ], + "numberOfBytes": "96" + }, + "t_struct(WithdrawalRequest)33689_storage": { + "encoding": "inplace", + "label": "struct XVSVaultStorageV1.WithdrawalRequest", + "members": [ + { + "astId": 33684, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "amount", + "offset": 0, + "slot": "0", + "type": "t_uint256" + }, + { + "astId": 33686, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "lockedUntil", + "offset": 0, + "slot": "1", + "type": "t_uint128" + }, + { + "astId": 33688, + "contract": "contracts/XVSVault/XVSVault.sol:XVSVault", + "label": "afterUpgrade", + "offset": 16, + "slot": "1", + "type": "t_uint128" + } + ], + "numberOfBytes": "64" + }, + "t_uint128": { + "encoding": "inplace", + "label": "uint128", + "numberOfBytes": "16" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint32": { + "encoding": "inplace", + "label": "uint32", + "numberOfBytes": "4" + }, + "t_uint96": { + "encoding": "inplace", + "label": "uint96", + "numberOfBytes": "12" + } + } + } +} diff --git a/deployments/sepolia/XVSVaultProxy.json b/deployments/sepolia/XVSVaultProxy.json new file mode 100644 index 000000000..5d508dd7c --- /dev/null +++ b/deployments/sepolia/XVSVaultProxy.json @@ -0,0 +1,352 @@ +{ + "address": "0xf929Fa887F171d315b5187D5563055663Fe404B3", + "abi": [ + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingXVSVaultImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x79e2bba59441bbe8c59204cde13bc61a32265dcf7ea291aa0757c287a0f48173", + "receipt": { + "to": null, + "from": "0x03862dFa5D0be8F64509C001cb8C6188194469DF", + "contractAddress": "0xf929Fa887F171d315b5187D5563055663Fe404B3", + "transactionIndex": 15, + "gasUsed": "394440", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x30268047adf0b71cd950b3ae264af66e01250a613babdeb9bb54f33a4e4f0ef8", + "transactionHash": "0x79e2bba59441bbe8c59204cde13bc61a32265dcf7ea291aa0757c287a0f48173", + "logs": [], + "blockNumber": 4749649, + "cumulativeGasUsed": "709440", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "b0e08c65414d4fb3a80b2146b3c121f2", + "metadata": "{\"compiler\":{\"version\":\"0.5.16+commit.9c3226ce\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"NewAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldImplementation\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"NewImplementation\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPendingAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPendingAdmin\",\"type\":\"address\"}],\"name\":\"NewPendingAdmin\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPendingImplementation\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPendingImplementation\",\"type\":\"address\"}],\"name\":\"NewPendingImplementation\",\"type\":\"event\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"constant\":false,\"inputs\":[],\"name\":\"_acceptAdmin\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"_acceptImplementation\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPendingAdmin\",\"type\":\"address\"}],\"name\":\"_setPendingAdmin\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPendingImplementation\",\"type\":\"address\"}],\"name\":\"_setPendingImplementation\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"pendingXVSVaultImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"methods\":{\"_acceptAdmin()\":{\"details\":\"Admin function for pending admin to accept role and update admin\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_acceptImplementation()\":{\"details\":\"Admin function for new implementation to accept it's role as implementation\",\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"},\"_setPendingAdmin(address)\":{\"details\":\"Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\",\"params\":{\"newPendingAdmin\":\"New pending admin.\"},\"return\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"title\":\"XVS Vault Proxy\"},\"userdoc\":{\"methods\":{\"_acceptAdmin()\":{\"notice\":\"Accepts transfer of admin rights. msg.sender must be pendingAdmin\"},\"_acceptImplementation()\":{\"notice\":\"Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation\"},\"_setPendingAdmin(address)\":{\"notice\":\"Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\"},\"_setPendingImplementation(address)\":{\"notice\":\"* Admin Functions **\"}},\"notice\":\"XVS Vault Proxy contract\"}},\"settings\":{\"compilationTarget\":{\"contracts/XVSVault/XVSVaultProxy.sol\":\"XVSVaultProxy\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.5.16;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n}\\n\",\"keccak256\":\"0xa4f8ba3fbd95f83e1a056be73247f4c715904d94f47639d226746c2bc7b13484\"},\"contracts/Utils/IBEP20.sol\":{\"content\":\"pragma solidity ^0.5.0;\\n\\n/**\\n * @dev Interface of the BEP20 standard as defined in the EIP. Does not include\\n * the optional functions; to access them see {BEP20Detailed}.\\n */\\ninterface IBEP20 {\\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\":\"0x839b08895eb1ad83502d3631e8e9e3a856d2a8c63c46f070d604af7b26c62c07\"},\"contracts/Utils/SafeMath.sol\":{\"content\":\"pragma solidity ^0.5.16;\\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 return add(a, b, \\\"SafeMath: addition 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 function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, errorMessage);\\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 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 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 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\":\"0x9431fd772ed4abc038cdfe9ce6c0066897bd1685ad45848748d1952935d5b8ef\"},\"contracts/XVSVault/XVSVaultErrorReporter.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\ncontract XVSVaultErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0xa79877a281d024f0d03dbf1842a36a972ee6c1aa36ba93e3d646726d40684a26\"},\"contracts/XVSVault/XVSVaultProxy.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"./XVSVaultStorage.sol\\\";\\nimport \\\"./XVSVaultErrorReporter.sol\\\";\\n\\n/**\\n * @title XVS Vault Proxy\\n * @author Venus\\n * @notice XVS Vault Proxy contract\\n */\\ncontract XVSVaultProxy is XVSVaultAdminStorage, XVSVaultErrorReporter {\\n /**\\n * @notice Emitted when pendingXVSVaultImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingXVSVaultImplementation is accepted, which means XVS Vault implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() public {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingXVSVaultImplementation;\\n\\n pendingXVSVaultImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation\\n if (msg.sender != pendingXVSVaultImplementation) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = implementation;\\n address oldPendingImplementation = pendingXVSVaultImplementation;\\n\\n implementation = pendingXVSVaultImplementation;\\n\\n pendingXVSVaultImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, implementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n function() external payable {\\n // delegate all other functions to current implementation\\n (bool success, ) = implementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize)\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize)\\n }\\n default {\\n return(free_mem_ptr, returndatasize)\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xb39af917833659fe38f2f76924deda420babed8259b27741dc6cb402ade4d124\"},\"contracts/XVSVault/XVSVaultStorage.sol\":{\"content\":\"pragma solidity ^0.5.16;\\n\\nimport \\\"../Utils/SafeMath.sol\\\";\\nimport \\\"../Utils/IBEP20.sol\\\";\\nimport \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract XVSVaultAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of XVS Vault\\n */\\n address public implementation;\\n\\n /**\\n * @notice Pending brains of XVS Vault\\n */\\n address public pendingXVSVaultImplementation;\\n}\\n\\ncontract XVSVaultStorageV1 is XVSVaultAdminStorage {\\n /// @notice Guard variable for re-entrancy checks\\n bool internal _notEntered;\\n\\n /// @notice The reward token store\\n address public xvsStore;\\n\\n /// @notice The xvs token address\\n address public xvsAddress;\\n\\n // Reward tokens created per block indentified by reward token address.\\n mapping(address => uint256) public rewardTokenAmountsPerBlock;\\n\\n /// @notice Info of each user.\\n struct UserInfo {\\n uint256 amount;\\n uint256 rewardDebt;\\n uint256 pendingWithdrawals;\\n }\\n\\n // Info of each pool.\\n struct PoolInfo {\\n IBEP20 token; // Address of token contract to stake.\\n uint256 allocPoint; // How many allocation points assigned to this pool.\\n uint256 lastRewardBlock; // Last block number that reward tokens distribution occurs.\\n uint256 accRewardPerShare; // Accumulated per share, times 1e12. See below.\\n uint256 lockPeriod; // Min time between withdrawal request and its execution.\\n }\\n\\n // Infomation about a withdrawal request\\n struct WithdrawalRequest {\\n uint256 amount;\\n uint128 lockedUntil;\\n uint128 afterUpgrade;\\n }\\n\\n // Info of each user that stakes tokens.\\n mapping(address => mapping(uint256 => mapping(address => UserInfo))) internal userInfos;\\n\\n // Info of each pool.\\n mapping(address => PoolInfo[]) public poolInfos;\\n\\n // Total allocation points. Must be the sum of all allocation points in all pools.\\n mapping(address => uint256) public totalAllocPoints;\\n\\n // Info of requested but not yet executed withdrawals\\n mapping(address => mapping(uint256 => mapping(address => WithdrawalRequest[]))) internal withdrawalRequests;\\n\\n /// @notice DEPRECATED A record of each accounts delegate (before the voting power fix)\\n mapping(address => address) private __oldDelegatesSlot;\\n\\n /// @notice A checkpoint for marking number of votes from a given block\\n struct Checkpoint {\\n uint32 fromBlock;\\n uint96 votes;\\n }\\n\\n /// @notice DEPRECATED A record of votes checkpoints for each account, by index (before the voting power fix)\\n mapping(address => mapping(uint32 => Checkpoint)) private __oldCheckpointsSlot;\\n\\n /// @notice DEPRECATED The number of checkpoints for each account (before the voting power fix)\\n mapping(address => uint32) private __oldNumCheckpointsSlot;\\n\\n /// @notice A record of states for signing / validating signatures\\n mapping(address => uint) public nonces;\\n\\n /// @notice The EIP-712 typehash for the contract's domain\\n bytes32 public constant DOMAIN_TYPEHASH =\\n keccak256(\\\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\\\");\\n\\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\\n bytes32 public constant DELEGATION_TYPEHASH =\\n keccak256(\\\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\\\");\\n}\\n\\ncontract XVSVaultStorage is XVSVaultStorageV1 {\\n /// @notice A record of each accounts delegate\\n mapping(address => address) public delegates;\\n\\n /// @notice A record of votes checkpoints for each account, by index\\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\\n\\n /// @notice The number of checkpoints for each account\\n mapping(address => uint32) public numCheckpoints;\\n\\n /// @notice Tracks pending withdrawals for all users for a particular reward token and pool id\\n mapping(address => mapping(uint256 => uint256)) internal totalPendingWithdrawals;\\n\\n /// @notice pause indicator for Vault\\n bool public vaultPaused;\\n\\n /// @notice if the token is added to any of the pools\\n mapping(address => bool) public isStakedToken;\\n\\n /// @notice Amount we owe to users because of failed transfer attempts\\n mapping(address => mapping(address => uint256)) public pendingRewardTransfers;\\n\\n /// @notice Prime token contract address\\n IPrime public primeToken;\\n\\n /// @notice Reward token for which prime token is issued for staking\\n address public primeRewardToken;\\n\\n /// @notice Pool ID for which prime token is issued for staking\\n uint256 public primePoolId;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\",\"keccak256\":\"0x6389c160d86eab54ce1a8a5138c39f38d858381b7d8881d146cd937feab3dac9\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50600080546001600160a01b031916331790556105c3806100326000396000f3fe60806040526004361061007b5760003560e01c8063de0368b21161004e578063de0368b21461019e578063e992a041146101b3578063e9c714f2146101e6578063f851a440146101fb5761007b565b806326782247146100fe5780635c60da1b1461012f578063b71d1a0c14610144578063c1e8033414610189575b6002546040516000916001600160a01b031690829036908083838082843760405192019450600093509091505080830381855af49150503d80600081146100de576040519150601f19603f3d011682016040523d82523d6000602084013e6100e3565b606091505b505090506040513d6000823e8180156100fa573d82f35b3d82fd5b34801561010a57600080fd5b50610113610210565b604080516001600160a01b039092168252519081900360200190f35b34801561013b57600080fd5b5061011361021f565b34801561015057600080fd5b506101776004803603602081101561016757600080fd5b50356001600160a01b031661022e565b60408051918252519081900360200190f35b34801561019557600080fd5b506101776102bf565b3480156101aa57600080fd5b506101136103a4565b3480156101bf57600080fd5b50610177600480360360208110156101d657600080fd5b50356001600160a01b03166103b3565b3480156101f257600080fd5b50610177610437565b34801561020757600080fd5b50610113610512565b6001546001600160a01b031681565b6002546001600160a01b031681565b600080546001600160a01b031633146102545761024d60016002610521565b90506102ba565b600180546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a160005b9150505b919050565b6003546000906001600160a01b031633146102e6576102df600180610521565b90506103a1565b60028054600380546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a92908290030190a1600354604080516001600160a01b038085168252909216602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160005b925050505b90565b6003546001600160a01b031681565b600080546001600160a01b031633146103d25761024d60016003610521565b600380546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160006102b6565b6001546000906001600160a01b03163314610458576102df60016000610521565b60008054600180546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600154604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a1600061039c565b6000546001600160a01b031681565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083600181111561055057fe5b83600381111561055c57fe5b604080519283526020830191909152600082820152519081900360600190a182600181111561058757fe5b939250505056fea265627a7a723158203a98485c54ef57fd84a4faf886b55d7092617cb9d58c7425ac25306994a23d1764736f6c63430005100032", + "deployedBytecode": "0x60806040526004361061007b5760003560e01c8063de0368b21161004e578063de0368b21461019e578063e992a041146101b3578063e9c714f2146101e6578063f851a440146101fb5761007b565b806326782247146100fe5780635c60da1b1461012f578063b71d1a0c14610144578063c1e8033414610189575b6002546040516000916001600160a01b031690829036908083838082843760405192019450600093509091505080830381855af49150503d80600081146100de576040519150601f19603f3d011682016040523d82523d6000602084013e6100e3565b606091505b505090506040513d6000823e8180156100fa573d82f35b3d82fd5b34801561010a57600080fd5b50610113610210565b604080516001600160a01b039092168252519081900360200190f35b34801561013b57600080fd5b5061011361021f565b34801561015057600080fd5b506101776004803603602081101561016757600080fd5b50356001600160a01b031661022e565b60408051918252519081900360200190f35b34801561019557600080fd5b506101776102bf565b3480156101aa57600080fd5b506101136103a4565b3480156101bf57600080fd5b50610177600480360360208110156101d657600080fd5b50356001600160a01b03166103b3565b3480156101f257600080fd5b50610177610437565b34801561020757600080fd5b50610113610512565b6001546001600160a01b031681565b6002546001600160a01b031681565b600080546001600160a01b031633146102545761024d60016002610521565b90506102ba565b600180546001600160a01b038481166001600160a01b0319831681179093556040805191909216808252602082019390935281517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a9929181900390910190a160005b9150505b919050565b6003546000906001600160a01b031633146102e6576102df600180610521565b90506103a1565b60028054600380546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927fd604de94d45953f9138079ec1b82d533cb2160c906d1076d1f7ed54befbca97a92908290030190a1600354604080516001600160a01b038085168252909216602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160005b925050505b90565b6003546001600160a01b031681565b600080546001600160a01b031633146103d25761024d60016003610521565b600380546001600160a01b038481166001600160a01b0319831617928390556040805192821680845293909116602083015280517fe945ccee5d701fc83f9b8aa8ca94ea4219ec1fcbd4f4cab4f0ea57c5c3e1d8159281900390910190a160006102b6565b6001546000906001600160a01b03163314610458576102df60016000610521565b60008054600180546001600160a01b038082166001600160a01b031980861682179687905590921690925560408051938316808552949092166020840152815190927ff9ffabca9c8276e99321725bcb43fb076a6c66a54b7f21c4e8146d8519b417dc92908290030190a1600154604080516001600160a01b038085168252909216602083015280517fca4f2f25d0898edd99413412fb94012f9e54ec8142f9b093e7720646a95b16a99281900390910190a1600061039c565b6000546001600160a01b031681565b60007f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa083600181111561055057fe5b83600381111561055c57fe5b604080519283526020830191909152600082820152519081900360600190a182600181111561058757fe5b939250505056fea265627a7a723158203a98485c54ef57fd84a4faf886b55d7092617cb9d58c7425ac25306994a23d1764736f6c63430005100032", + "devdoc": { + "author": "Venus", + "methods": { + "_acceptAdmin()": { + "details": "Admin function for pending admin to accept role and update admin", + "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)" + }, + "_acceptImplementation()": { + "details": "Admin function for new implementation to accept it's role as implementation", + "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)" + }, + "_setPendingAdmin(address)": { + "details": "Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.", + "params": { + "newPendingAdmin": "New pending admin." + }, + "return": "uint 0=success, otherwise a failure (see ErrorReporter.sol for details)" + } + }, + "title": "XVS Vault Proxy" + }, + "userdoc": { + "methods": { + "_acceptAdmin()": { + "notice": "Accepts transfer of admin rights. msg.sender must be pendingAdmin" + }, + "_acceptImplementation()": { + "notice": "Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation" + }, + "_setPendingAdmin(address)": { + "notice": "Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer." + }, + "_setPendingImplementation(address)": { + "notice": "* Admin Functions **" + } + }, + "notice": "XVS Vault Proxy contract" + }, + "storageLayout": { + "storage": [ + { + "astId": 33645, + "contract": "contracts/XVSVault/XVSVaultProxy.sol:XVSVaultProxy", + "label": "admin", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 33647, + "contract": "contracts/XVSVault/XVSVaultProxy.sol:XVSVaultProxy", + "label": "pendingAdmin", + "offset": 0, + "slot": "1", + "type": "t_address" + }, + { + "astId": 33649, + "contract": "contracts/XVSVault/XVSVaultProxy.sol:XVSVaultProxy", + "label": "implementation", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 33651, + "contract": "contracts/XVSVault/XVSVaultProxy.sol:XVSVaultProxy", + "label": "pendingXVSVaultImplementation", + "offset": 0, + "slot": "3", + "type": "t_address" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + } + } + } +} diff --git a/deployments/sepolia/solcInputs/b0e08c65414d4fb3a80b2146b3c121f2.json b/deployments/sepolia/solcInputs/b0e08c65414d4fb3a80b2146b3c121f2.json new file mode 100644 index 000000000..0a7273efa --- /dev/null +++ b/deployments/sepolia/solcInputs/b0e08c65414d4fb3a80b2146b3c121f2.json @@ -0,0 +1,345 @@ +{ + "language": "Solidity", + "sources": { + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.5.16;\n\nimport \"./IAccessControlManagerV5.sol\";\n\n/**\n * @title AccessControlledV5\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.5.16)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\ncontract AccessControlledV5 {\n /// @notice Access control manager contract\n IAccessControlManagerV5 private _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV5) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV5(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert(\"Unauthorized\");\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/GovernorBravoDelegate.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"./GovernorBravoInterfaces.sol\";\n\n/**\n * @title GovernorBravoDelegate\n * @notice Venus Governance latest on chain governance includes several new features including variable proposal routes and fine grained pause control.\n * Variable routes for proposals allows for governance paramaters such as voting threshold and timelocks to be customized based on the risk level and\n * impact of the proposal. Added granularity to the pause control mechanism allows governance to pause individual actions on specific markets,\n * which reduces impact on the protocol as a whole. This is particularly useful when applied to isolated pools.\n *\n * The goal of **Governance** is to increase governance efficiency, while mitigating and eliminating malicious or erroneous proposals.\n *\n * ## Details\n *\n * Governance has **3 main contracts**: **GovernanceBravoDelegate, XVSVault, XVS** token.\n *\n * - XVS token is the protocol token used for protocol users to cast their vote on submitted proposals.\n * - XVSVault is the main staking contract for XVS. Users first stake their XVS in the vault and receive voting power proportional to their staked\n * tokens that they can use to vote on proposals. Users also can choose to delegate their voting power to other users.\n *\n * # Governor Bravo\n *\n * `GovernanceBravoDelegate` is main Venus Governance contract. Users interact with it to:\n * - Submit new proposal\n * - Vote on a proposal\n * - Cancel a proposal\n * - Queue a proposal for execution with a timelock executor contract.\n * `GovernanceBravoDelegate` uses the XVSVault to get restrict certain actions based on a user's voting power. The governance rules it inforces are:\n * - A user's voting power must be greater than the `proposalThreshold` to submit a proposal\n * - If a user's voting power drops below certain amount, anyone can cancel the the proposal. The governance guardian and proposal creator can also\n * cancel a proposal at anytime before it is queued for execution.\n *\n * ## Venus Improvement Proposal\n *\n * Venus Governance allows for Venus Improvement Proposals (VIPs) to be categorized based on their impact and risk levels. This allows for optimizing proposals\n * execution to allow for things such as expediting interest rate changes and quickly updating risk parameters, while moving slower on other types of proposals\n * that can prevent a larger risk to the protocol and are not urgent. There are three different types of VIPs with different proposal paramters:\n *\n * - `NORMAL`\n * - `FASTTRACK`\n * - `CRITICAL`\n *\n * When initializing the `GovernorBravo` contract, the parameters for the three routes are set. The parameters are:\n *\n * - `votingDelay`: The delay in blocks between submitting a proposal and when voting begins\n * - `votingPeriod`: The number of blocks where voting will be open\n * - `proposalThreshold`: The number of votes required in order submit a proposal\n *\n * There is also a separate timelock executor contract for each route, which is used to dispatch the VIP for execution, giving even more control over the\n * flow of each type of VIP.\n *\n * ## Voting\n *\n * After a VIP is proposed, voting is opened after the `votingDelay` has passed. For example, if `votingDelay = 0`, then voting will begin in the next block\n * after the proposal has been submitted. After the delay, the proposal state is `ACTIVE` and users can cast their vote `for`, `against`, or `abstain`,\n * weighted by their total voting power (tokens + delegated voting power). Abstaining from a voting allows for a vote to be cast and optionally include a\n * comment, without the incrementing for or against vote count. The total voting power for the user is obtained by calling XVSVault's `getPriorVotes`.\n *\n * `GovernorBravoDelegate` also accepts [EIP-712](https://eips.ethereum.org/EIPS/eip-712) signatures for voting on proposals via the external function\n * `castVoteBySig`.\n *\n * ## Delegating\n *\n * A users voting power includes the amount of staked XVS the have staked as well as the votes delegate to them. Delegating is the process of a user loaning\n * their voting power to another, so that the latter has the combined voting power of both users. This is an important feature because it allows for a user\n * to let another user who they trust propose or vote in their place.\n *\n * The delegation of votes happens through the `XVSVault` contract by calling the `delegate` or `delegateBySig` functions. These same functions can revert\n * vote delegation by calling the same function with a value of `0`.\n */\ncontract GovernorBravoDelegate is GovernorBravoDelegateInterface, GovernorBravoDelegateStorageV2, GovernorBravoEvents {\n /// @notice The name of this contract\n string public constant name = \"Venus Governor Bravo\";\n\n /// @notice The minimum setable proposal threshold\n uint public constant MIN_PROPOSAL_THRESHOLD = 150000e18; // 150,000 Xvs\n\n /// @notice The maximum setable proposal threshold\n uint public constant MAX_PROPOSAL_THRESHOLD = 300000e18; //300,000 Xvs\n\n /// @notice The minimum setable voting period\n uint public constant MIN_VOTING_PERIOD = 20 * 60 * 3; // About 3 hours, 3 secs per block\n\n /// @notice The max setable voting period\n uint public constant MAX_VOTING_PERIOD = 20 * 60 * 24 * 14; // About 2 weeks, 3 secs per block\n\n /// @notice The min setable voting delay\n uint public constant MIN_VOTING_DELAY = 1;\n\n /// @notice The max setable voting delay\n uint public constant MAX_VOTING_DELAY = 20 * 60 * 24 * 7; // About 1 week, 3 secs per block\n\n /// @notice The number of votes in support of a proposal required in order for a quorum to be reached and for a vote to succeed\n uint public constant quorumVotes = 600000e18; // 600,000 = 2% of Xvs\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH =\n keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the ballot struct used by the contract\n bytes32 public constant BALLOT_TYPEHASH = keccak256(\"Ballot(uint256 proposalId,uint8 support)\");\n\n /**\n * @notice Used to initialize the contract during delegator contructor\n * @param xvsVault_ The address of the XvsVault\n * @param proposalConfigs_ Governance configs for each governance route\n * @param timelocks Timelock addresses for each governance route\n */\n function initialize(\n address xvsVault_,\n ProposalConfig[] memory proposalConfigs_,\n TimelockInterface[] memory timelocks,\n address guardian_\n ) public {\n require(address(proposalTimelocks[0]) == address(0), \"GovernorBravo::initialize: cannot initialize twice\");\n require(msg.sender == admin, \"GovernorBravo::initialize: admin only\");\n require(xvsVault_ != address(0), \"GovernorBravo::initialize: invalid xvs address\");\n require(guardian_ != address(0), \"GovernorBravo::initialize: invalid guardian\");\n require(\n timelocks.length == uint8(ProposalType.CRITICAL) + 1,\n \"GovernorBravo::initialize:number of timelocks should match number of governance routes\"\n );\n require(\n proposalConfigs_.length == uint8(ProposalType.CRITICAL) + 1,\n \"GovernorBravo::initialize:number of proposal configs should match number of governance routes\"\n );\n\n xvsVault = XvsVaultInterface(xvsVault_);\n proposalMaxOperations = 10;\n guardian = guardian_;\n\n //Set parameters for each Governance Route\n uint256 arrLength = proposalConfigs_.length;\n for (uint256 i; i < arrLength; ++i) {\n require(\n proposalConfigs_[i].votingPeriod >= MIN_VOTING_PERIOD,\n \"GovernorBravo::initialize: invalid min voting period\"\n );\n require(\n proposalConfigs_[i].votingPeriod <= MAX_VOTING_PERIOD,\n \"GovernorBravo::initialize: invalid max voting period\"\n );\n require(\n proposalConfigs_[i].votingDelay >= MIN_VOTING_DELAY,\n \"GovernorBravo::initialize: invalid min voting delay\"\n );\n require(\n proposalConfigs_[i].votingDelay <= MAX_VOTING_DELAY,\n \"GovernorBravo::initialize: invalid max voting delay\"\n );\n require(\n proposalConfigs_[i].proposalThreshold >= MIN_PROPOSAL_THRESHOLD,\n \"GovernorBravo::initialize: invalid min proposal threshold\"\n );\n require(\n proposalConfigs_[i].proposalThreshold <= MAX_PROPOSAL_THRESHOLD,\n \"GovernorBravo::initialize: invalid max proposal threshold\"\n );\n require(address(timelocks[i]) != address(0), \"GovernorBravo::initialize:invalid timelock address\");\n\n proposalConfigs[i] = proposalConfigs_[i];\n proposalTimelocks[i] = timelocks[i];\n }\n }\n\n /**\n * @notice Function used to propose a new proposal. Sender must have delegates above the proposal threshold.\n * targets, values, signatures, and calldatas must be of equal length\n * @dev NOTE: Proposals with duplicate set of actions can not be queued for execution. If the proposals consists\n * of duplicate actions, it's recommended to split those actions into separate proposals\n * @param targets Target addresses for proposal calls\n * @param values BNB values for proposal calls\n * @param signatures Function signatures for proposal calls\n * @param calldatas Calldatas for proposal calls\n * @param description String description of the proposal\n * @param proposalType the type of the proposal (e.g NORMAL, FASTTRACK, CRITICAL)\n * @return Proposal id of new proposal\n */\n function propose(\n address[] memory targets,\n uint[] memory values,\n string[] memory signatures,\n bytes[] memory calldatas,\n string memory description,\n ProposalType proposalType\n ) public returns (uint) {\n // Reject proposals before initiating as Governor\n require(initialProposalId != 0, \"GovernorBravo::propose: Governor Bravo not active\");\n require(\n xvsVault.getPriorVotes(msg.sender, sub256(block.number, 1)) >=\n proposalConfigs[uint8(proposalType)].proposalThreshold,\n \"GovernorBravo::propose: proposer votes below proposal threshold\"\n );\n require(\n targets.length == values.length &&\n targets.length == signatures.length &&\n targets.length == calldatas.length,\n \"GovernorBravo::propose: proposal function information arity mismatch\"\n );\n require(targets.length != 0, \"GovernorBravo::propose: must provide actions\");\n require(targets.length <= proposalMaxOperations, \"GovernorBravo::propose: too many actions\");\n\n uint latestProposalId = latestProposalIds[msg.sender];\n if (latestProposalId != 0) {\n ProposalState proposersLatestProposalState = state(latestProposalId);\n require(\n proposersLatestProposalState != ProposalState.Active,\n \"GovernorBravo::propose: one live proposal per proposer, found an already active proposal\"\n );\n require(\n proposersLatestProposalState != ProposalState.Pending,\n \"GovernorBravo::propose: one live proposal per proposer, found an already pending proposal\"\n );\n }\n\n uint startBlock = add256(block.number, proposalConfigs[uint8(proposalType)].votingDelay);\n uint endBlock = add256(startBlock, proposalConfigs[uint8(proposalType)].votingPeriod);\n\n proposalCount++;\n Proposal memory newProposal = Proposal({\n id: proposalCount,\n proposer: msg.sender,\n eta: 0,\n targets: targets,\n values: values,\n signatures: signatures,\n calldatas: calldatas,\n startBlock: startBlock,\n endBlock: endBlock,\n forVotes: 0,\n againstVotes: 0,\n abstainVotes: 0,\n canceled: false,\n executed: false,\n proposalType: uint8(proposalType)\n });\n\n proposals[newProposal.id] = newProposal;\n latestProposalIds[newProposal.proposer] = newProposal.id;\n\n emit ProposalCreated(\n newProposal.id,\n msg.sender,\n targets,\n values,\n signatures,\n calldatas,\n startBlock,\n endBlock,\n description,\n uint8(proposalType)\n );\n return newProposal.id;\n }\n\n /**\n * @notice Queues a proposal of state succeeded\n * @param proposalId The id of the proposal to queue\n */\n function queue(uint proposalId) external {\n require(\n state(proposalId) == ProposalState.Succeeded,\n \"GovernorBravo::queue: proposal can only be queued if it is succeeded\"\n );\n Proposal storage proposal = proposals[proposalId];\n uint eta = add256(block.timestamp, proposalTimelocks[uint8(proposal.proposalType)].delay());\n for (uint i; i < proposal.targets.length; ++i) {\n queueOrRevertInternal(\n proposal.targets[i],\n proposal.values[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n eta,\n uint8(proposal.proposalType)\n );\n }\n proposal.eta = eta;\n emit ProposalQueued(proposalId, eta);\n }\n\n function queueOrRevertInternal(\n address target,\n uint value,\n string memory signature,\n bytes memory data,\n uint eta,\n uint8 proposalType\n ) internal {\n require(\n !proposalTimelocks[proposalType].queuedTransactions(\n keccak256(abi.encode(target, value, signature, data, eta))\n ),\n \"GovernorBravo::queueOrRevertInternal: identical proposal action already queued at eta\"\n );\n proposalTimelocks[proposalType].queueTransaction(target, value, signature, data, eta);\n }\n\n /**\n * @notice Executes a queued proposal if eta has passed\n * @param proposalId The id of the proposal to execute\n */\n function execute(uint proposalId) external {\n require(\n state(proposalId) == ProposalState.Queued,\n \"GovernorBravo::execute: proposal can only be executed if it is queued\"\n );\n Proposal storage proposal = proposals[proposalId];\n proposal.executed = true;\n for (uint i; i < proposal.targets.length; ++i) {\n proposalTimelocks[uint8(proposal.proposalType)].executeTransaction(\n proposal.targets[i],\n proposal.values[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n proposal.eta\n );\n }\n emit ProposalExecuted(proposalId);\n }\n\n /**\n * @notice Cancels a proposal only if sender is the proposer, or proposer delegates dropped below proposal threshold\n * @param proposalId The id of the proposal to cancel\n */\n function cancel(uint proposalId) external {\n require(state(proposalId) != ProposalState.Executed, \"GovernorBravo::cancel: cannot cancel executed proposal\");\n\n Proposal storage proposal = proposals[proposalId];\n require(\n msg.sender == guardian ||\n msg.sender == proposal.proposer ||\n xvsVault.getPriorVotes(proposal.proposer, sub256(block.number, 1)) <\n proposalConfigs[proposal.proposalType].proposalThreshold,\n \"GovernorBravo::cancel: proposer above threshold\"\n );\n\n proposal.canceled = true;\n for (uint i = 0; i < proposal.targets.length; i++) {\n proposalTimelocks[proposal.proposalType].cancelTransaction(\n proposal.targets[i],\n proposal.values[i],\n proposal.signatures[i],\n proposal.calldatas[i],\n proposal.eta\n );\n }\n\n emit ProposalCanceled(proposalId);\n }\n\n /**\n * @notice Gets actions of a proposal\n * @param proposalId the id of the proposal\n * @return targets, values, signatures, and calldatas of the proposal actions\n */\n function getActions(\n uint proposalId\n )\n external\n view\n returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas)\n {\n Proposal storage p = proposals[proposalId];\n return (p.targets, p.values, p.signatures, p.calldatas);\n }\n\n /**\n * @notice Gets the receipt for a voter on a given proposal\n * @param proposalId the id of proposal\n * @param voter The address of the voter\n * @return The voting receipt\n */\n function getReceipt(uint proposalId, address voter) external view returns (Receipt memory) {\n return proposals[proposalId].receipts[voter];\n }\n\n /**\n * @notice Gets the state of a proposal\n * @param proposalId The id of the proposal\n * @return Proposal state\n */\n function state(uint proposalId) public view returns (ProposalState) {\n require(\n proposalCount >= proposalId && proposalId > initialProposalId,\n \"GovernorBravo::state: invalid proposal id\"\n );\n Proposal storage proposal = proposals[proposalId];\n if (proposal.canceled) {\n return ProposalState.Canceled;\n } else if (block.number <= proposal.startBlock) {\n return ProposalState.Pending;\n } else if (block.number <= proposal.endBlock) {\n return ProposalState.Active;\n } else if (proposal.forVotes <= proposal.againstVotes || proposal.forVotes < quorumVotes) {\n return ProposalState.Defeated;\n } else if (proposal.eta == 0) {\n return ProposalState.Succeeded;\n } else if (proposal.executed) {\n return ProposalState.Executed;\n } else if (\n block.timestamp >= add256(proposal.eta, proposalTimelocks[uint8(proposal.proposalType)].GRACE_PERIOD())\n ) {\n return ProposalState.Expired;\n } else {\n return ProposalState.Queued;\n }\n }\n\n /**\n * @notice Cast a vote for a proposal\n * @param proposalId The id of the proposal to vote on\n * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n */\n function castVote(uint proposalId, uint8 support) external {\n emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), \"\");\n }\n\n /**\n * @notice Cast a vote for a proposal with a reason\n * @param proposalId The id of the proposal to vote on\n * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n * @param reason The reason given for the vote by the voter\n */\n function castVoteWithReason(uint proposalId, uint8 support, string calldata reason) external {\n emit VoteCast(msg.sender, proposalId, support, castVoteInternal(msg.sender, proposalId, support), reason);\n }\n\n /**\n * @notice Cast a vote for a proposal by signature\n * @dev External function that accepts EIP-712 signatures for voting on proposals.\n * @param proposalId The id of the proposal to vote on\n * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n * @param v recovery id of ECDSA signature\n * @param r part of the ECDSA sig output\n * @param s part of the ECDSA sig output\n */\n function castVoteBySig(uint proposalId, uint8 support, uint8 v, bytes32 r, bytes32 s) external {\n bytes32 domainSeparator = keccak256(\n abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainIdInternal(), address(this))\n );\n bytes32 structHash = keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support));\n bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n address signatory = ecrecover(digest, v, r, s);\n require(signatory != address(0), \"GovernorBravo::castVoteBySig: invalid signature\");\n emit VoteCast(signatory, proposalId, support, castVoteInternal(signatory, proposalId, support), \"\");\n }\n\n /**\n * @notice Internal function that caries out voting logic\n * @param voter The voter that is casting their vote\n * @param proposalId The id of the proposal to vote on\n * @param support The support value for the vote. 0=against, 1=for, 2=abstain\n * @return The number of votes cast\n */\n function castVoteInternal(address voter, uint proposalId, uint8 support) internal returns (uint96) {\n require(state(proposalId) == ProposalState.Active, \"GovernorBravo::castVoteInternal: voting is closed\");\n require(support <= 2, \"GovernorBravo::castVoteInternal: invalid vote type\");\n Proposal storage proposal = proposals[proposalId];\n Receipt storage receipt = proposal.receipts[voter];\n require(receipt.hasVoted == false, \"GovernorBravo::castVoteInternal: voter already voted\");\n uint96 votes = xvsVault.getPriorVotes(voter, proposal.startBlock);\n\n if (support == 0) {\n proposal.againstVotes = add256(proposal.againstVotes, votes);\n } else if (support == 1) {\n proposal.forVotes = add256(proposal.forVotes, votes);\n } else if (support == 2) {\n proposal.abstainVotes = add256(proposal.abstainVotes, votes);\n }\n\n receipt.hasVoted = true;\n receipt.support = support;\n receipt.votes = votes;\n\n return votes;\n }\n\n /**\n * @notice Sets the new governance guardian\n * @param newGuardian the address of the new guardian\n */\n function _setGuardian(address newGuardian) external {\n require(msg.sender == guardian || msg.sender == admin, \"GovernorBravo::_setGuardian: admin or guardian only\");\n require(newGuardian != address(0), \"GovernorBravo::_setGuardian: cannot live without a guardian\");\n address oldGuardian = guardian;\n guardian = newGuardian;\n\n emit NewGuardian(oldGuardian, newGuardian);\n }\n\n /**\n * @notice Initiate the GovernorBravo contract\n * @dev Admin only. Sets initial proposal id which initiates the contract, ensuring a continuous proposal id count\n * @param governorAlpha The address for the Governor to continue the proposal id count from\n */\n function _initiate(address governorAlpha) external {\n require(msg.sender == admin, \"GovernorBravo::_initiate: admin only\");\n require(initialProposalId == 0, \"GovernorBravo::_initiate: can only initiate once\");\n proposalCount = GovernorAlphaInterface(governorAlpha).proposalCount();\n initialProposalId = proposalCount;\n for (uint256 i; i < uint8(ProposalType.CRITICAL) + 1; ++i) {\n proposalTimelocks[i].acceptAdmin();\n }\n }\n\n /**\n * @notice Set max proposal operations\n * @dev Admin only.\n * @param proposalMaxOperations_ Max proposal operations\n */\n function _setProposalMaxOperations(uint proposalMaxOperations_) external {\n require(msg.sender == admin, \"GovernorBravo::_setProposalMaxOperations: admin only\");\n uint oldProposalMaxOperations = proposalMaxOperations;\n proposalMaxOperations = proposalMaxOperations_;\n\n emit ProposalMaxOperationsUpdated(oldProposalMaxOperations, proposalMaxOperations_);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n */\n function _setPendingAdmin(address newPendingAdmin) external {\n // Check caller = admin\n require(msg.sender == admin, \"GovernorBravo:_setPendingAdmin: admin only\");\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n */\n function _acceptAdmin() external {\n // Check caller is pendingAdmin and pendingAdmin ≠ address(0)\n require(\n msg.sender == pendingAdmin && msg.sender != address(0),\n \"GovernorBravo:_acceptAdmin: pending admin only\"\n );\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n }\n\n function add256(uint256 a, uint256 b) internal pure returns (uint) {\n uint c = a + b;\n require(c >= a, \"addition overflow\");\n return c;\n }\n\n function sub256(uint256 a, uint256 b) internal pure returns (uint) {\n require(b <= a, \"subtraction underflow\");\n return a - b;\n }\n\n function getChainIdInternal() internal pure returns (uint) {\n uint chainId;\n assembly {\n chainId := chainid()\n }\n return chainId;\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/GovernorBravoInterfaces.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\n/**\n * @title GovernorBravoEvents\n * @author Venus\n * @notice Set of events emitted by the GovernorBravo contracts.\n */\ncontract GovernorBravoEvents {\n /// @notice An event emitted when a new proposal is created\n event ProposalCreated(\n uint id,\n address proposer,\n address[] targets,\n uint[] values,\n string[] signatures,\n bytes[] calldatas,\n uint startBlock,\n uint endBlock,\n string description,\n uint8 proposalType\n );\n\n /// @notice An event emitted when a vote has been cast on a proposal\n /// @param voter The address which casted a vote\n /// @param proposalId The proposal id which was voted on\n /// @param support Support value for the vote. 0=against, 1=for, 2=abstain\n /// @param votes Number of votes which were cast by the voter\n /// @param reason The reason given for the vote by the voter\n event VoteCast(address indexed voter, uint proposalId, uint8 support, uint votes, string reason);\n\n /// @notice An event emitted when a proposal has been canceled\n event ProposalCanceled(uint id);\n\n /// @notice An event emitted when a proposal has been queued in the Timelock\n event ProposalQueued(uint id, uint eta);\n\n /// @notice An event emitted when a proposal has been executed in the Timelock\n event ProposalExecuted(uint id);\n\n /// @notice An event emitted when the voting delay is set\n event VotingDelaySet(uint oldVotingDelay, uint newVotingDelay);\n\n /// @notice An event emitted when the voting period is set\n event VotingPeriodSet(uint oldVotingPeriod, uint newVotingPeriod);\n\n /// @notice Emitted when implementation is changed\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /// @notice Emitted when proposal threshold is set\n event ProposalThresholdSet(uint oldProposalThreshold, uint newProposalThreshold);\n\n /// @notice Emitted when pendingAdmin is changed\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /// @notice Emitted when pendingAdmin is accepted, which means admin is updated\n event NewAdmin(address oldAdmin, address newAdmin);\n\n /// @notice Emitted when the new guardian address is set\n event NewGuardian(address oldGuardian, address newGuardian);\n\n /// @notice Emitted when the maximum number of operations in one proposal is updated\n event ProposalMaxOperationsUpdated(uint oldMaxOperations, uint newMaxOperations);\n}\n\n/**\n * @title GovernorBravoDelegatorStorage\n * @author Venus\n * @notice Storage layout of the `GovernorBravoDelegator` contract\n */\ncontract GovernorBravoDelegatorStorage {\n /// @notice Administrator for this contract\n address public admin;\n\n /// @notice Pending administrator for this contract\n address public pendingAdmin;\n\n /// @notice Active brains of Governor\n address public implementation;\n}\n\n/**\n * @title GovernorBravoDelegateStorageV1\n * @dev For future upgrades, do not change GovernorBravoDelegateStorageV1. Create a new\n * contract which implements GovernorBravoDelegateStorageV1 and following the naming convention\n * GovernorBravoDelegateStorageVX.\n */\ncontract GovernorBravoDelegateStorageV1 is GovernorBravoDelegatorStorage {\n /// @notice DEPRECATED The delay before voting on a proposal may take place, once proposed, in blocks\n uint public votingDelay;\n\n /// @notice DEPRECATED The duration of voting on a proposal, in blocks\n uint public votingPeriod;\n\n /// @notice DEPRECATED The number of votes required in order for a voter to become a proposer\n uint public proposalThreshold;\n\n /// @notice Initial proposal id set at become\n uint public initialProposalId;\n\n /// @notice The total number of proposals\n uint public proposalCount;\n\n /// @notice The address of the Venus Protocol Timelock\n TimelockInterface public timelock;\n\n /// @notice The address of the Venus governance token\n XvsVaultInterface public xvsVault;\n\n /// @notice The official record of all proposals ever proposed\n mapping(uint => Proposal) public proposals;\n\n /// @notice The latest proposal for each proposer\n mapping(address => uint) public latestProposalIds;\n\n struct Proposal {\n /// @notice Unique id for looking up a proposal\n uint id;\n /// @notice Creator of the proposal\n address proposer;\n /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds\n uint eta;\n /// @notice the ordered list of target addresses for calls to be made\n address[] targets;\n /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made\n uint[] values;\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 The block at which voting begins: holders must delegate their votes prior to this block\n uint startBlock;\n /// @notice The block at which voting ends: votes must be cast prior to this block\n uint endBlock;\n /// @notice Current number of votes in favor of this proposal\n uint forVotes;\n /// @notice Current number of votes in opposition to this proposal\n uint againstVotes;\n /// @notice Current number of votes for abstaining for this proposal\n uint abstainVotes;\n /// @notice Flag marking whether the proposal has been canceled\n bool canceled;\n /// @notice Flag marking whether the proposal has been executed\n bool executed;\n /// @notice Receipts of ballots for the entire set of voters\n mapping(address => Receipt) receipts;\n /// @notice The type of the proposal\n uint8 proposalType;\n }\n\n /// @notice Ballot receipt record for a voter\n struct Receipt {\n /// @notice Whether or not a vote has been cast\n bool hasVoted;\n /// @notice Whether or not the voter supports the proposal or abstains\n uint8 support;\n /// @notice The number of votes the voter had, which were cast\n uint96 votes;\n }\n\n /// @notice Possible states that a proposal may be in\n enum ProposalState {\n Pending,\n Active,\n Canceled,\n Defeated,\n Succeeded,\n Queued,\n Expired,\n Executed\n }\n\n /// @notice The maximum number of actions that can be included in a proposal\n uint public proposalMaxOperations;\n\n /// @notice A privileged role that can cancel any proposal\n address public guardian;\n}\n\n/**\n * @title GovernorBravoDelegateStorageV2\n * @dev For future upgrades, do not change GovernorBravoDelegateStorageV1. Create a new\n * contract which implements GovernorBravoDelegateStorageV2 and following the naming convention\n * GovernorBravoDelegateStorageVX.\n */\ncontract GovernorBravoDelegateStorageV2 is GovernorBravoDelegateStorageV1 {\n enum ProposalType {\n NORMAL,\n FASTTRACK,\n CRITICAL\n }\n\n /// @notice mapping containing configuration for each proposal type\n mapping(uint => GovernorBravoDelegateInterface.ProposalConfig) public proposalConfigs;\n\n /// @notice mapping containing Timelock addresses for each proposal type\n mapping(uint => TimelockInterface) public proposalTimelocks;\n}\n\n/**\n * @title TimelockInterface\n * @author Venus\n * @notice Interface implemented by the GovernorBravoDelegate contract.\n */\ninterface GovernorBravoDelegateInterface {\n struct ProposalConfig {\n /// @notice The delay before voting on a proposal may take place, once proposed, in blocks\n uint256 votingDelay;\n /// @notice The duration of voting on a proposal, in blocks\n uint256 votingPeriod;\n /// @notice The number of votes required in order for a voter to become a proposer\n uint256 proposalThreshold;\n }\n\n function initialize(\n address xvsVault_,\n ProposalConfig[] calldata proposalConfigs_,\n TimelockInterface[] calldata timelocks,\n address guardian_\n ) external;\n}\n\n/**\n * @title TimelockInterface\n * @author Venus\n * @notice Interface implemented by the Timelock contract.\n */\ninterface TimelockInterface {\n function delay() external view returns (uint);\n\n function GRACE_PERIOD() external view returns (uint);\n\n function acceptAdmin() external;\n\n function queuedTransactions(bytes32 hash) external view returns (bool);\n\n function queueTransaction(\n address target,\n uint value,\n string calldata signature,\n bytes calldata data,\n uint eta\n ) external returns (bytes32);\n\n function cancelTransaction(\n address target,\n uint value,\n string calldata signature,\n bytes calldata data,\n uint eta\n ) external;\n\n function executeTransaction(\n address target,\n uint value,\n string calldata signature,\n bytes calldata data,\n uint eta\n ) external payable returns (bytes memory);\n}\n\ninterface XvsVaultInterface {\n function getPriorVotes(address account, uint blockNumber) external view returns (uint96);\n}\n\ninterface GovernorAlphaInterface {\n /// @notice The total number of proposals\n function proposalCount() external returns (uint);\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV5.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.5.16;\n\n/**\n * @title IAccessControlManagerV5\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV5` contract.\n */\ninterface IAccessControlManagerV5 {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n\n /**\n * @notice Gives a function call permission to one single account\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * \t\tMay emit a {RoleGranted} event.\n * @param contractAddress address of contract for which call permissions will be granted\n * @param functionSig signature e.g. \"functionName(uint,bool)\"\n */\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n /**\n * @notice Revokes an account's permission to a particular function call\n * @dev this function can be called only from Role Admin or DEFAULT_ADMIN_ROLE\n * \t\tMay emit a {RoleRevoked} event.\n * @param contractAddress address of contract for which call permissions will be revoked\n * @param functionSig signature e.g. \"functionName(uint,bool)\"\n */\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n /**\n * @notice Verifies if the given account can call a praticular contract's function\n * @dev Since the contract is calling itself this function, we can get contracts address with msg.sender\n * @param account address (eoa or contract) for which call permissions will be checked\n * @param functionSig signature e.g. \"functionName(uint,bool)\"\n * @return false if the user account cannot call the particular contract function\n *\n */\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "contracts/Comptroller/ComptrollerInterface.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VTokens/VToken.sol\";\nimport \"../Oracle/PriceOracle.sol\";\nimport \"../Tokens/VAI/VAIControllerInterface.sol\";\n\ncontract ComptrollerInterface {\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n bool public constant isComptroller = true;\n\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\n\n function exitMarket(address vToken) external returns (uint);\n\n /*** Policy Hooks ***/\n\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external returns (uint);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function getXVSAddress() public view returns (address);\n\n function markets(address) external view returns (bool, uint);\n\n function oracle() external view returns (PriceOracle);\n\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function claimVenus(address) external;\n\n function venusAccrued(address) external view returns (uint);\n\n function venusSupplySpeeds(address) external view returns (uint);\n\n function venusBorrowSpeeds(address) external view returns (uint);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function venusSupplierIndex(address, address) external view returns (uint);\n\n function venusInitialIndex() external view returns (uint224);\n\n function venusBorrowerIndex(address, address) external view returns (uint);\n\n function venusBorrowState(address) external view returns (uint224, uint32);\n\n function venusSupplyState(address) external view returns (uint224, uint32);\n\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\n\n function vaiController() external view returns (VAIControllerInterface);\n\n function liquidationIncentiveMantissa() external view returns (uint);\n\n function protocolPaused() external view returns (bool);\n\n function mintedVAIs(address user) external view returns (uint);\n\n function vaiMintRate() external view returns (uint);\n}\n\ninterface IVAIVault {\n function updatePendingRewards() external;\n}\n\ninterface IComptroller {\n function liquidationIncentiveMantissa() external view returns (uint);\n\n /*** Treasury Data ***/\n function treasuryAddress() external view returns (address);\n\n function treasuryPercent() external view returns (uint);\n}\n" + }, + "contracts/Comptroller/ComptrollerLensInterface.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"../Tokens/VTokens/VToken.sol\";\n\ninterface ComptrollerLensInterface {\n function liquidateCalculateSeizeTokens(\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function liquidateVAICalculateSeizeTokens(\n address comptroller,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function getHypotheticalAccountLiquidity(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount\n ) external view returns (uint, uint, uint);\n}\n" + }, + "contracts/Comptroller/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity ^0.5.16;\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { PriceOracle } from \"../Oracle/PriceOracle.sol\";\nimport { VAIControllerInterface } from \"../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterface } from \"./ComptrollerLensInterface.sol\";\nimport { IPrime } from \"../Tokens/Prime/IPrime.sol\";\n\ncontract UnitrollerAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of Unitroller\n */\n address public comptrollerImplementation;\n\n /**\n * @notice Pending brains of Unitroller\n */\n address public pendingComptrollerImplementation;\n}\n\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\n /**\n * @notice Oracle which gives the price of any given asset\n */\n PriceOracle public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n */\n uint256 public liquidationIncentiveMantissa;\n\n /**\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\n */\n uint256 public maxAssets;\n\n /**\n * @notice Per-account mapping of \"assets you are in\", capped by maxAssets\n */\n mapping(address => VToken[]) public accountAssets;\n\n struct Market {\n /// @notice Whether or not this market is listed\n bool isListed;\n /**\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\n * For instance, 0.9 to allow borrowing 90% of collateral value.\n * Must be between 0 and 1, and stored as a mantissa.\n */\n uint256 collateralFactorMantissa;\n /// @notice Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n /// @notice Whether or not this market receives XVS\n bool isVenus;\n }\n\n /**\n * @notice Official mapping of vTokens -> Market metadata\n * @dev Used e.g. to determine if a market is supported\n */\n mapping(address => Market) public markets;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n address public pauseGuardian;\n\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\n bool private _mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool private _borrowGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal transferGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal seizeGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal borrowGuardianPaused;\n\n struct VenusMarketState {\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\n uint224 index;\n /// @notice The block number the index was last updated at\n uint32 block;\n }\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice The rate at which the flywheel distributes XVS, per block\n uint256 internal venusRate;\n\n /// @notice The portion of venusRate that each market currently receives\n mapping(address => uint256) internal venusSpeeds;\n\n /// @notice The Venus market supply state for each market\n mapping(address => VenusMarketState) public venusSupplyState;\n\n /// @notice The Venus market borrow state for each market\n mapping(address => VenusMarketState) public venusBorrowState;\n\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\n\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\n\n /// @notice The XVS accrued but not yet transferred to each user\n mapping(address => uint256) public venusAccrued;\n\n /// @notice The Address of VAIController\n VAIControllerInterface public vaiController;\n\n /// @notice The minted VAI amount to each user\n mapping(address => uint256) public mintedVAIs;\n\n /// @notice VAI Mint Rate as a percentage\n uint256 public vaiMintRate;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n bool public mintVAIGuardianPaused;\n bool public repayVAIGuardianPaused;\n\n /**\n * @notice Pause/Unpause whole protocol actions\n */\n bool public protocolPaused;\n\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\n uint256 private venusVAIRate;\n}\n\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\n uint256 public venusVAIVaultRate;\n\n // address of VAI Vault\n address public vaiVaultAddress;\n\n // start block of release to VAI Vault\n uint256 public releaseStartBlock;\n\n // minimum release amount to VAI Vault\n uint256 public minReleaseAmount;\n}\n\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\n address public borrowCapGuardian;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address. Defaults to zero which corresponds to unlimited borrowing.\n mapping(address => uint256) public borrowCaps;\n}\n\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\n /// @notice Treasury Guardian address\n address public treasuryGuardian;\n\n /// @notice Treasury address\n address public treasuryAddress;\n\n /// @notice Fee percent of accrued interest with decimal 18\n uint256 public treasuryPercent;\n}\n\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\n mapping(address => uint256) private venusContributorSpeeds;\n\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\n mapping(address => uint256) private lastContributorBlock;\n}\n\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\n address public liquidatorContract;\n}\n\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\n ComptrollerLensInterface public comptrollerLens;\n}\n\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\n mapping(address => uint256) public supplyCaps;\n}\n\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\n /// @notice AccessControlManager address\n address internal accessControl;\n\n enum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n }\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\n}\n\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public venusBorrowSpeeds;\n\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public venusSupplySpeeds;\n}\n\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\n /// @notice Whether the delegate is allowed to borrow on behalf of the borrower\n //mapping(address borrower => mapping (address delegate => bool approved)) public approvedDelegates;\n mapping(address => mapping(address => bool)) public approvedDelegates;\n}\n\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\n mapping(address => bool) public isForcedLiquidationEnabled;\n}\n\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\n }\n\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\n // facet addresses\n address[] internal _facetAddresses;\n}\n\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\n /// @notice Prime token address\n IPrime public prime;\n}\n" + }, + "contracts/Comptroller/Diamond/Diamond.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\npragma experimental ABIEncoderV2;\n\nimport { IDiamondCut } from \"./interfaces/IDiamondCut.sol\";\nimport { Unitroller, ComptrollerV14Storage } from \"../Unitroller.sol\";\n\n/**\n * @title Diamond\n * @author Venus\n * @notice This contract contains functions related to facets\n */\ncontract Diamond is IDiamondCut, ComptrollerV14Storage {\n /// @notice Emitted when functions are added, replaced or removed to facets\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut);\n\n struct Facet {\n address facetAddress;\n bytes4[] functionSelectors;\n }\n\n /**\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\n * @param unitroller Address of the unitroller\n */\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n /**\n * @notice To add function selectors to the facet's mapping\n * @dev Allows the contract admin to add function selectors\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\n */\n function diamondCut(IDiamondCut.FacetCut[] memory diamondCut_) public {\n require(msg.sender == admin, \"only unitroller admin can\");\n libDiamondCut(diamondCut_);\n }\n\n /**\n * @notice Get all function selectors mapped to the facet address\n * @param facet Address of the facet\n * @return selectors Array of function selectors\n */\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\n return _facetFunctionSelectors[facet].functionSelectors;\n }\n\n /**\n * @notice Get facet position in the _facetFunctionSelectors through facet address\n * @param facet Address of the facet\n * @return Position of the facet\n */\n function facetPosition(address facet) external view returns (uint256) {\n return _facetFunctionSelectors[facet].facetAddressPosition;\n }\n\n /**\n * @notice Get all facet addresses\n * @return facetAddresses Array of facet addresses\n */\n function facetAddresses() external view returns (address[] memory) {\n return _facetAddresses;\n }\n\n /**\n * @notice Get facet address and position through function selector\n * @param functionSelector function selector\n * @return FacetAddressAndPosition facet address and position\n */\n function facetAddress(\n bytes4 functionSelector\n ) external view returns (ComptrollerV14Storage.FacetAddressAndPosition memory) {\n return _selectorToFacetAndPosition[functionSelector];\n }\n\n /**\n * @notice Get all facets address and their function selector\n * @return facets_ Array of Facet\n */\n function facets() external view returns (Facet[] memory) {\n uint256 facetsLength = _facetAddresses.length;\n Facet[] memory facets_ = new Facet[](facetsLength);\n for (uint256 i; i < facetsLength; ++i) {\n address facet = _facetAddresses[i];\n facets_[i].facetAddress = facet;\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\n }\n return facets_;\n }\n\n /**\n * @notice To add function selectors to the facets' mapping\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\n */\n function libDiamondCut(IDiamondCut.FacetCut[] memory diamondCut_) internal {\n uint256 diamondCutLength = diamondCut_.length;\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\n IDiamondCut.FacetCutAction action = diamondCut_[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n }\n emit DiamondCut(diamondCut_);\n }\n\n /**\n * @notice Add function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to add in the mapping\n */\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress == address(0), \"LibDiamondCut: Can't add function that already exists\");\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to replace in the mapping\n */\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress != facetAddress, \"LibDiamondCut: Can't replace function with same function\");\n removeFunction(oldFacetAddress, selector);\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Remove function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to remove in the mapping\n */\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n uint256 functionSelectorsLength = functionSelectors.length;\n require(functionSelectorsLength != 0, \"LibDiamondCut: No selectors in facet to cut\");\n // if function does not exist then do nothing and revert\n require(facetAddress == address(0), \"LibDiamondCut: Remove facet address must be address(0)\");\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n removeFunction(oldFacetAddress, selector);\n }\n }\n\n /**\n * @notice Add new facet to the proxy\n * @param facetAddress Address of the facet\n */\n function addFacet(address facetAddress) internal {\n enforceHasContractCode(facetAddress, \"Diamond: New facet has no code\");\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\n _facetAddresses.push(facetAddress);\n }\n\n /**\n * @notice Add function selector to the facet's address mapping\n * @param selector funciton selector need to be added\n * @param selectorPosition funciton selector position\n * @param facetAddress Address of the facet\n */\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\n }\n\n /**\n * @notice Remove function selector to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param selector function selectors need to remove in the mapping\n */\n function removeFunction(address facetAddress, bytes4 selector) internal {\n require(facetAddress != address(0), \"LibDiamondCut: Can't remove function that doesn't exist\");\n\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\n // if not the same then replace selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\n delete _selectorToFacetAndPosition[selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\n }\n _facetAddresses.pop();\n delete _facetFunctionSelectors[facetAddress];\n }\n }\n\n /**\n * @dev Ensure that the given address has contract code deployed\n * @param _contract The address to check for contract code\n * @param _errorMessage The error message to display if the contract code is not deployed\n */\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\n uint256 contractSize;\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize != 0, _errorMessage);\n }\n\n // Find facet for function that is called and execute the\n // function if a facet is found and return any value.\n function() external payable {\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\n require(facet != address(0), \"Diamond: Function does not exist\");\n // Execute public function from facet using delegatecall and return any value.\n assembly {\n // copy function selector and any arguments\n calldatacopy(0, 0, calldatasize())\n // execute function call using the facet\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\n // get any return value\n returndatacopy(0, 0, returndatasize())\n // return any return value or error back to the caller\n switch result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/DiamondConsolidated.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"./facets/MarketFacet.sol\";\nimport \"./facets/PolicyFacet.sol\";\nimport \"./facets/RewardFacet.sol\";\nimport \"./facets/SetterFacet.sol\";\nimport \"./Diamond.sol\";\n\n/**\n * @title DiamondConsolidated\n * @author Venus\n * @notice This contract contains the functions defined in the different facets of the Diamond, plus the getters to the public variables.\n * This contract cannot be deployed, due to its size. Its main purpose is to allow the easy generation of an ABI and the typechain to interact with the\n * Unitroller contract in a simple way\n */\ncontract DiamondConsolidated is Diamond, MarketFacet, PolicyFacet, RewardFacet, SetterFacet {}\n" + }, + "contracts/Comptroller/Diamond/facets/FacetBase.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { VToken, ComptrollerErrorReporter, ExponentialNoError } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { IVAIVault } from \"../../../Comptroller/ComptrollerInterface.sol\";\nimport { ComptrollerV14Storage } from \"../../../Comptroller/ComptrollerStorage.sol\";\nimport { IAccessControlManagerV5 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV5.sol\";\n\nimport { SafeBEP20, IBEP20 } from \"../../../Utils/SafeBEP20.sol\";\n\n/**\n * @title FacetBase\n * @author Venus\n * @notice This facet contract contains functions related to access and checks\n */\ncontract FacetBase is ComptrollerV14Storage, ExponentialNoError, ComptrollerErrorReporter {\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when XVS is distributed to VAI Vault\n event DistributedVAIVaultVenus(uint256 amount);\n\n using SafeBEP20 for IBEP20;\n\n /// @notice The initial Venus index for a market\n uint224 public constant venusInitialIndex = 1e36;\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\n // closeFactorMantissa must not exceed this value\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\n\n /// @notice Reverts if the protocol is paused\n function checkProtocolPauseState() internal view {\n require(!protocolPaused, \"protocol is paused\");\n }\n\n /// @notice Reverts if a certain action is paused on a market\n function checkActionPauseState(address market, Action action) internal view {\n require(!actionPaused(market, action), \"action is paused\");\n }\n\n /// @notice Reverts if the caller is not admin\n function ensureAdmin() internal view {\n require(msg.sender == admin, \"only admin can\");\n }\n\n /// @notice Checks the passed address is nonzero\n function ensureNonzeroAddress(address someone) internal pure {\n require(someone != address(0), \"can't be zero address\");\n }\n\n /// @notice Reverts if the market is not listed\n function ensureListed(Market storage market) internal view {\n require(market.isListed, \"market not listed\");\n }\n\n /// @notice Reverts if the caller is neither admin nor the passed address\n function ensureAdminOr(address privilegedAddress) internal view {\n require(msg.sender == admin || msg.sender == privilegedAddress, \"access denied\");\n }\n\n /// @notice Checks the caller is allowed to call the specified fuction\n function ensureAllowed(string memory functionSig) internal view {\n require(IAccessControlManagerV5(accessControl).isAllowedToCall(msg.sender, functionSig), \"access denied\");\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param action Action id\n * @param market vToken address\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][uint256(action)];\n }\n\n /**\n * @notice Get the latest block number\n */\n function getBlockNumber() internal view returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Get the latest block number with the safe32 check\n */\n function getBlockNumberAsUint32() internal view returns (uint32) {\n return safe32(getBlockNumber(), \"block # > 32 bits\");\n }\n\n /**\n * @notice Transfer XVS to VAI Vault\n */\n function releaseToVault() internal {\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\n return;\n }\n\n uint256 xvsBalance = IBEP20(getXVSAddress()).balanceOf(address(this));\n if (xvsBalance == 0) {\n return;\n }\n\n uint256 actualAmount;\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\n // releaseAmount = venusVAIVaultRate * deltaBlocks\n uint256 _releaseAmount = mul_(venusVAIVaultRate, deltaBlocks);\n\n if (xvsBalance >= _releaseAmount) {\n actualAmount = _releaseAmount;\n } else {\n actualAmount = xvsBalance;\n }\n\n if (actualAmount < minReleaseAmount) {\n return;\n }\n\n releaseStartBlock = getBlockNumber();\n\n IBEP20(getXVSAddress()).safeTransfer(vaiVaultAddress, actualAmount);\n emit DistributedVAIVaultVenus(actualAmount);\n\n IVAIVault(vaiVaultAddress).updatePendingRewards();\n }\n\n /**\n * @notice Return the address of the XVS token\n * @return The address of XVS\n */\n function getXVSAddress() public pure returns (address) {\n return 0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63;\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return (possible error code,\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidityInternal(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) internal view returns (Error, uint256, uint256) {\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\n address(this),\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount\n );\n return (Error(err), liquidity, shortfall);\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n * @return Success indicator for whether the market was entered\n */\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n ensureListed(marketToJoin);\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return Error.NO_ERROR;\n }\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n\n return Error.NO_ERROR;\n }\n\n /**\n * @notice Checks for the user is allowed to redeem tokens\n * @param vToken Address of the market\n * @param redeemer Address of the user\n * @param redeemTokens Amount of tokens to redeem\n * @return Success indicator for redeem is allowed or not\n */\n function redeemAllowedInternal(\n address vToken,\n address redeemer,\n uint256 redeemTokens\n ) internal view returns (uint256) {\n ensureListed(markets[vToken]);\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!markets[vToken].accountMembership[redeemer]) {\n return uint256(Error.NO_ERROR);\n }\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n return uint256(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/MarketFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { IMarketFacet } from \"../interfaces/IMarketFacet.sol\";\nimport { FacetBase, VToken } from \"./FacetBase.sol\";\n\n/**\n * @title MarketFacet\n * @author Venus\n * @dev This facet contains all the methods related to the market's management in the pool\n * @notice This facet contract contains functions regarding markets\n */\ncontract MarketFacet is IMarketFacet, FacetBase {\n /// @notice Emitted when an admin supports a market\n event MarketListed(VToken indexed vToken);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when the borrowing delegate rights are updated for an account\n event DelegateUpdated(address indexed borrower, address indexed delegate, bool allowDelegatedBorrows);\n\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() public pure returns (bool) {\n return true;\n }\n\n /**\n * @notice Returns the assets an account has entered\n * @param account The address of the account to pull assets for\n * @return A dynamic list with the assets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n return accountAssets[account];\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market\n * @return The list of market addresses\n */\n function getAllMarkets() external view returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\n address(this),\n vTokenBorrowed,\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\n address(this),\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Returns whether the given account is entered in the given asset\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the asset, otherwise false\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return markets[address(vToken)].accountMembership[account];\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return Success indicator for whether each corresponding market was entered\n */\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\n }\n\n return results;\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow\n * @param vTokenAddress The address of the asset to be removed\n * @return Whether or not the account successfully exited the market\n */\n function exitMarket(address vTokenAddress) external returns (uint256) {\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\n require(oErr == 0, \"getAccountSnapshot failed\"); // semi-opaque error code\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\n if (allowed != 0) {\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\n }\n\n Market storage marketToExit = markets[address(vToken)];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return uint256(Error.NO_ERROR);\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n uint256 i;\n for (; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n userAssetList[i] = userAssetList[len - 1];\n userAssetList.length--;\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(i < len);\n\n emit MarketExited(vToken, msg.sender);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Allows a privileged role to add and list markets to the Comptroller\n * @param vToken The address of the market (token) to list\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _supportMarket(VToken vToken) external returns (uint256) {\n ensureAllowed(\"_supportMarket(address)\");\n\n if (markets[address(vToken)].isListed) {\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\n }\n\n vToken.isVToken(); // Sanity check to make sure its really a VToken\n\n // Note that isVenus is not in active use anymore\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.isVenus = false;\n newMarket.collateralFactorMantissa = 0;\n\n _addMarketInternal(vToken);\n _initializeMarket(address(vToken));\n\n emit MarketListed(vToken);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Grants or revokes the borrowing delegate rights to / from an account\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\n * will see the debt on their account\n * @param delegate The address to update the rights for\n * @param allowBorrows Whether to grant (true) or revoke (false) the rights\n */\n function updateDelegate(address delegate, bool allowBorrows) external {\n _updateDelegate(msg.sender, delegate, allowBorrows);\n }\n\n function _updateDelegate(address borrower, address delegate, bool allowBorrows) internal {\n approvedDelegates[borrower][delegate] = allowBorrows;\n emit DelegateUpdated(borrower, delegate, allowBorrows);\n }\n\n function _addMarketInternal(VToken vToken) internal {\n uint256 allMarketsLength = allMarkets.length;\n for (uint256 i; i < allMarketsLength; ++i) {\n require(allMarkets[i] != vToken, \"already added\");\n }\n allMarkets.push(vToken);\n }\n\n function _initializeMarket(address vToken) internal {\n uint32 blockNumber = getBlockNumberAsUint32();\n\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = venusInitialIndex;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = venusInitialIndex;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/PolicyFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { IPolicyFacet } from \"../interfaces/IPolicyFacet.sol\";\n\nimport { XVSRewardsHelper, VToken } from \"./XVSRewardsHelper.sol\";\n\n/**\n * @title PolicyFacet\n * @author Venus\n * @dev This facet contains all the hooks used while transferring the assets\n * @notice This facet contract contains all the external pre-hook functions related to vToken\n */\ncontract PolicyFacet is IPolicyFacet, XVSRewardsHelper {\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.MINT);\n ensureListed(markets[vToken]);\n\n uint256 supplyCap = supplyCaps[vToken];\n require(supplyCap != 0, \"market supply cap is 0\");\n\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n require(nextTotalSupply <= supplyCap, \"market supply cap reached\");\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, minter);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being minted\n * @param minter The address minting the tokens\n * @param actualMintAmount The amount of the underlying asset being minted\n * @param mintTokens The number of tokens being minted\n */\n // solhint-disable-next-line no-unused-vars\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(minter, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REDEEM);\n\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, redeemer);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being redeemed\n * @param redeemer The address redeeming the tokens\n * @param redeemAmount The amount of the underlying asset being redeemed\n * @param redeemTokens The number of tokens being redeemed\n */\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\n require(redeemTokens != 0 || redeemAmount == 0, \"redeemTokens zero\");\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.BORROW);\n\n ensureListed(markets[vToken]);\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n require(msg.sender == vToken, \"sender must be vToken\");\n\n // attempt to add borrower to the market\n Error err = addToMarketInternal(VToken(vToken), borrower);\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n }\n\n if (oracle.getUnderlyingPrice(VToken(vToken)) == 0) {\n return uint256(Error.PRICE_ERROR);\n }\n\n uint256 borrowCap = borrowCaps[vToken];\n // Borrow cap of 0 corresponds to unlimited borrowing\n if (borrowCap != 0) {\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\n require(nextTotalBorrows < borrowCap, \"market borrow cap reached\");\n }\n\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset whose underlying is being borrowed\n * @param borrower The address borrowing the underlying\n * @param borrowAmount The amount of the underlying asset requested to borrow\n */\n // solhint-disable-next-line no-unused-vars\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param payer The account which would repay the asset\n * @param borrower The account which borrowed the asset\n * @param repayAmount The amount of the underlying asset the account would repay\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function repayBorrowAllowed(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 repayAmount // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REPAY);\n ensureListed(markets[vToken]);\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being repaid\n * @param payer The address repaying the borrow\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n */\n function repayBorrowVerify(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n */\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256) {\n checkProtocolPauseState();\n\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\n return uint256(Error.UNAUTHORIZED);\n }\n\n ensureListed(markets[vTokenCollateral]);\n\n uint256 borrowBalance;\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n } else {\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\n }\n\n if (isForcedLiquidationEnabled[vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n return uint(Error.TOO_MUCH_REPAY);\n }\n return uint(Error.NO_ERROR);\n }\n\n /* The borrower must have shortfall in order to be liquidatable */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(borrower, VToken(address(0)), 0, 0);\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall == 0) {\n return uint256(Error.INSUFFICIENT_SHORTFALL);\n }\n\n // The liquidator may not repay more than what is allowed by the closeFactor\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\n return uint256(Error.TOO_MUCH_REPAY);\n }\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n * @param seizeTokens The amount of collateral token that will be seized\n */\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n // We've added VAIController as a borrowed token list check for seize\n ensureListed(market);\n\n if (!market.accountMembership[borrower]) {\n return uint256(Error.MARKET_NOT_COLLATERAL);\n }\n\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n }\n\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\n return uint256(Error.COMPTROLLER_MISMATCH);\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vTokenCollateral);\n distributeSupplierVenus(vTokenCollateral, borrower);\n distributeSupplierVenus(vTokenCollateral, liquidator);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, src);\n distributeSupplierVenus(vToken, dst);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being transferred\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n */\n // solhint-disable-next-line no-unused-vars\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(src, vToken);\n prime.accrueInterestAndUpdateScore(dst, vToken);\n }\n }\n\n /**\n * @notice Determine the current account liquidity wrt collateral requirements\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n * account shortfall below collateral requirements)\n */\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n account,\n VToken(address(0)),\n 0,\n 0\n );\n\n return (uint256(err), liquidity, shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return (possible error code (semi-opaque),\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n // setter functionality\n /**\n * @notice Set XVS speed for a single market\n * @dev Allows the contract admin to set XVS speed for a market\n * @param vTokens The market whose XVS speed to update\n * @param supplySpeeds New XVS speed for supply\n * @param borrowSpeeds New XVS speed for borrow\n */\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external {\n ensureAdmin();\n\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid input\");\n\n for (uint256 i; i < numTokens; ++i) {\n ensureNonzeroAddress(address(vTokens[i]));\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n ensureListed(markets[address(vToken)]);\n\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n\n updateVenusSupplyIndex(address(vToken));\n // Update speed and emit event\n venusSupplySpeeds[address(vToken)] = supplySpeed;\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/RewardFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { IRewardFacet } from \"../interfaces/IRewardFacet.sol\";\nimport { XVSRewardsHelper, VToken } from \"./XVSRewardsHelper.sol\";\nimport { SafeBEP20, IBEP20 } from \"../../../Utils/SafeBEP20.sol\";\nimport { VBep20Interface } from \"../../../Tokens/VTokens/VTokenInterfaces.sol\";\n\n/**\n * @title RewardFacet\n * @author Venus\n * @dev This facet contains all the methods related to the reward functionality\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\n */\ncontract RewardFacet is IRewardFacet, XVSRewardsHelper {\n /// @notice Emitted when Venus is granted by admin\n event VenusGranted(address indexed recipient, uint256 amount);\n\n using SafeBEP20 for IBEP20;\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets and VAI\n * @param holder The address to claim XVS for\n */\n function claimVenus(address holder) public {\n return claimVenus(holder, allMarkets);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in the specified markets\n * @param holder The address to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n */\n function claimVenus(address holder, VToken[] memory vTokens) public {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, vTokens, true, true);\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\n claimVenus(holders, vTokens, borrowers, suppliers, false);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\n * @param holder The address to claim XVS for\n */\n function claimVenusAsCollateral(address holder) external {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, allMarkets, true, true, true);\n }\n\n /**\n * @notice Transfer XVS to the user with user's shortfall considered\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\n * @param user The address of the user to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n * @param shortfall The shortfall of the user\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\n * @return The amount of XVS which was NOT transferred to the user\n */\n function grantXVSInternal(\n address user,\n uint256 amount,\n uint256 shortfall,\n bool collateral\n ) internal returns (uint256) {\n // If the user is blacklisted, they can't get XVS rewards\n require(\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\n \"Blacklisted\"\n );\n\n if (amount == 0 || amount > IBEP20(getXVSAddress()).balanceOf(address(this))) {\n return amount;\n }\n\n if (shortfall == 0) {\n IBEP20(getXVSAddress()).safeTransfer(user, amount);\n return 0;\n }\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\n // anything, otherwise, we will transfer the pending xvs as collateral to\n // vXVS token and mint vXVS for the user\n //\n // If mintBehalf failed, don't grant any xvs\n require(collateral, \"bankrupt\");\n\n IBEP20(getXVSAddress()).safeApprove(getXVSVTokenAddress(), 0);\n IBEP20(getXVSAddress()).safeApprove(getXVSVTokenAddress(), amount);\n require(\n VBep20Interface(getXVSVTokenAddress()).mintBehalf(user, amount) == uint256(Error.NO_ERROR),\n \"mint behalf error\"\n );\n\n // set venusAccrued[user] to 0\n return 0;\n }\n\n /*** Venus Distribution Admin ***/\n\n /**\n * @notice Transfer XVS to the recipient\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\n * Note: If there is not enough XVS, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n */\n function _grantXVS(address recipient, uint256 amount) external {\n ensureAdmin();\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\n require(amountLeft == 0, \"no xvs\");\n emit VenusGranted(recipient, amount);\n }\n\n /**\n * @notice Return the address of the XVS vToken\n * @return The address of XVS vToken\n */\n function getXVSVTokenAddress() public pure returns (address) {\n return 0x151B1e2635A717bcDc836ECd6FbB62B674FE3E1D;\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\n */\n function claimVenus(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) public {\n uint256 j;\n uint256 holdersLength = holders.length;\n uint256 vTokensLength = vTokens.length;\n for (uint256 i; i < vTokensLength; ++i) {\n VToken vToken = vTokens[i];\n ensureListed(markets[address(vToken)]);\n if (borrowers) {\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n for (j = 0; j < holdersLength; ++j) {\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\n }\n }\n if (suppliers) {\n updateVenusSupplyIndex(address(vToken));\n for (j = 0; j < holdersLength; ++j) {\n distributeSupplierVenus(address(vToken), holders[j]);\n }\n }\n }\n\n for (j = 0; j < holdersLength; ++j) {\n address holder = holders[j];\n // If there is a positive shortfall, the XVS reward is accrued,\n // but won't be granted to this holder\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(holder, VToken(address(0)), 0, 0);\n\n uint256 value = venusAccrued[holder];\n venusAccrued[holder] = 0;\n\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\n\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\n if (returnAmount != 0) {\n venusAccrued[holder] = returnAmount;\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/SetterFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { ISetterFacet } from \"../interfaces/ISetterFacet.sol\";\nimport { PriceOracle } from \"../../../Oracle/PriceOracle.sol\";\nimport { ComptrollerLensInterface } from \"../../ComptrollerLensInterface.sol\";\nimport { VAIControllerInterface } from \"../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { FacetBase, VToken } from \"./FacetBase.sol\";\nimport { IPrime } from \"../../../Tokens/Prime/IPrime.sol\";\n\n/**\n * @title SetterFacet\n * @author Venus\n * @dev This facet contains all the setters for the states\n * @notice This facet contract contains all the configurational setter functions\n */\ncontract SetterFacet is ISetterFacet, FacetBase {\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor is changed by admin\n event NewCollateralFactor(\n VToken indexed vToken,\n uint256 oldCollateralFactorMantissa,\n uint256 newCollateralFactorMantissa\n );\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(PriceOracle oldPriceOracle, PriceOracle newPriceOracle);\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when VAIController is changed\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\n\n /// @notice Emitted when VAI mint rate is changed by admin\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\n\n /// @notice Emitted when protocol state is changed by admin\n event ActionProtocolPaused(bool state);\n\n /// @notice Emitted when treasury guardian is changed\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\n\n /// @notice Emitted when treasury address is changed\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\n\n /// @notice Emitted when treasury percent is changed\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\n\n /// @notice Emitted when liquidator adress is changed\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\n\n /// @notice Emitted when ComptrollerLens address is changed\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\n\n /// @notice Emitted when pause guardian is changed\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\n\n /// @notice Emitted when VAI Vault info is changed\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\n\n /// @notice Emitted when Venus VAI Vault rate is changed\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\n\n /// @notice Emitted when prime token contract address is changed\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\n\n /// @notice Emitted when force liquidation enabled for a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /**\n * @notice Compare two addresses to ensure they are different\n * @param oldAddress The original address to compare\n * @param newAddress The new address to compare\n */\n modifier compareAddress(address oldAddress, address newAddress) {\n require(oldAddress != newAddress, \"old address is same as new address\");\n _;\n }\n\n /**\n * @notice Compare two values to ensure they are different\n * @param oldValue The original value to compare\n * @param newValue The new value to compare\n */\n modifier compareValue(uint256 oldValue, uint256 newValue) {\n require(oldValue != newValue, \"old value is same as new value\");\n _;\n }\n\n /**\n * @notice Sets a new price oracle for the comptroller\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPriceOracle(\n PriceOracle newOracle\n ) external compareAddress(address(oracle), address(newOracle)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(newOracle));\n\n // Track the old oracle for the comptroller\n PriceOracle oldOracle = oracle;\n\n // Set comptroller's oracle to newOracle\n oracle = newOracle;\n\n // Emit NewPriceOracle(oldOracle, newOracle)\n emit NewPriceOracle(oldOracle, newOracle);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets the closeFactor used when liquidating borrows\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function _setCloseFactor(\n uint256 newCloseFactorMantissa\n ) external compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\n\n //-- Check close factor <= 0.9\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\n //-- Check close factor >= 0.05\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\n\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\n }\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Allows the contract admin to set the address of access control of this contract\n * @param newAccessControlAddress New address for the access control\n * @return uint256 0=success, otherwise will revert\n */\n function _setAccessControl(\n address newAccessControlAddress\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newAccessControlAddress);\n\n address oldAccessControlAddress = accessControl;\n\n accessControl = newAccessControlAddress;\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev Allows a privileged role to set the collateralFactorMantissa\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function _setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa\n )\n external\n compareValue(markets[address(vToken)].collateralFactorMantissa, newCollateralFactorMantissa)\n returns (uint256)\n {\n // Check caller is allowed by access control manager\n ensureAllowed(\"_setCollateralFactor(address,uint256)\");\n ensureNonzeroAddress(address(vToken));\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n ensureListed(market);\n\n Exp memory newCollateralFactorExp = Exp({ mantissa: newCollateralFactorMantissa });\n\n //-- Check collateral factor <= 0.9\n Exp memory highLimit = Exp({ mantissa: collateralFactorMaxMantissa });\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(vToken) == 0) {\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\n }\n\n // Set market's collateral factor to new collateral factor, remember old value\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n\n // Emit event with asset, old collateral factor, and new collateral factor\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev Allows a privileged role to set the liquidationIncentiveMantissa\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function _setLiquidationIncentive(\n uint256 newLiquidationIncentiveMantissa\n ) external compareValue(liquidationIncentiveMantissa, newLiquidationIncentiveMantissa) returns (uint256) {\n ensureAllowed(\"_setLiquidationIncentive(uint256)\");\n\n require(newLiquidationIncentiveMantissa >= 1e18, \"incentive < 1e18\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Update the address of the liquidator contract\n * @dev Allows the contract admin to update the address of liquidator contract\n * @param newLiquidatorContract_ The new address of the liquidator contract\n */\n function _setLiquidatorContract(\n address newLiquidatorContract_\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newLiquidatorContract_);\n address oldLiquidatorContract = liquidatorContract;\n liquidatorContract = newLiquidatorContract_;\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\n }\n\n /**\n * @notice Admin function to change the Pause Guardian\n * @dev Allows the contract admin to change the Pause Guardian\n * @param newPauseGuardian The address of the new Pause Guardian\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _setPauseGuardian(\n address newPauseGuardian\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(newPauseGuardian);\n\n // Save current value for inclusion in log\n address oldPauseGuardian = pauseGuardian;\n // Store pauseGuardian with value newPauseGuardian\n pauseGuardian = newPauseGuardian;\n\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to unlimited borrowing\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to unlimited borrowing\n */\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n ensureAllowed(\"_setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n ensureAllowed(\"_setMarketSupplyCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numSupplyCaps = newSupplyCaps.length;\n\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @notice Set whole protocol pause/unpause state\n * @dev Allows a privileged role to pause/unpause protocol\n * @param state The new state (true=paused, false=unpaused)\n * @return bool The updated state of the protocol\n */\n function _setProtocolPaused(bool state) external returns (bool) {\n ensureAllowed(\"_setProtocolPaused(bool)\");\n\n protocolPaused = state;\n emit ActionProtocolPaused(state);\n return state;\n }\n\n /**\n * @notice Pause/unpause certain actions\n * @dev Allows a privileged role to pause/unpause the protocol action state\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n ensureAllowed(\"_setActionsPaused(address[],uint8[],bool)\");\n\n uint256 numMarkets = markets_.length;\n uint256 numActions = actions_.length;\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\n }\n }\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function setActionPausedInternal(address market, Action action, bool paused) internal {\n ensureListed(markets[market]);\n _actionPaused[market][uint256(action)] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @notice Sets a new VAI controller\n * @dev Admin function to set a new VAI controller\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIController(\n VAIControllerInterface vaiController_\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(vaiController_));\n\n VAIControllerInterface oldVaiController = vaiController;\n vaiController = vaiController_;\n emit NewVAIController(oldVaiController, vaiController_);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the VAI mint rate\n * @param newVAIMintRate The new VAI mint rate to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIMintRate(\n uint256 newVAIMintRate\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n uint256 oldVAIMintRate = vaiMintRate;\n vaiMintRate = newVAIMintRate;\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the minted VAI amount of the `owner`\n * @param owner The address of the account to set\n * @param amount The amount of VAI to set to the account\n * @return The number of minted VAI by `owner`\n */\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\n checkProtocolPauseState();\n\n // Pausing is a very serious situation - we revert to sound the alarms\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \"VAI is paused\");\n // Check caller is vaiController\n if (msg.sender != address(vaiController)) {\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\n }\n mintedVAIs[owner] = amount;\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the treasury data.\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\n * @param newTreasuryAddress The new address of the treasury to be set\n * @param newTreasuryPercent The new treasury percent to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256) {\n // Check caller is admin\n ensureAdminOr(treasuryGuardian);\n\n require(newTreasuryPercent < 1e18, \"percent >= 100%\");\n ensureNonzeroAddress(newTreasuryGuardian);\n ensureNonzeroAddress(newTreasuryAddress);\n\n address oldTreasuryGuardian = treasuryGuardian;\n address oldTreasuryAddress = treasuryAddress;\n uint256 oldTreasuryPercent = treasuryPercent;\n\n treasuryGuardian = newTreasuryGuardian;\n treasuryAddress = newTreasuryAddress;\n treasuryPercent = newTreasuryPercent;\n\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\n\n return uint256(Error.NO_ERROR);\n }\n\n /*** Venus Distribution ***/\n\n /**\n * @dev Set ComptrollerLens contract address\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptrollerLens(\n ComptrollerLensInterface comptrollerLens_\n ) external compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the amount of XVS distributed per block to VAI Vault\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\n */\n function _setVenusVAIVaultRate(\n uint256 venusVAIVaultRate_\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\n ensureAdmin();\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\n venusVAIVaultRate = venusVAIVaultRate_;\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\n }\n\n /**\n * @notice Set the VAI Vault infos\n * @param vault_ The address of the VAI Vault\n * @param releaseStartBlock_ The start block of release to VAI Vault\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\n */\n function _setVAIVaultInfo(\n address vault_,\n uint256 releaseStartBlock_,\n uint256 minReleaseAmount_\n ) external compareAddress(vaiVaultAddress, vault_) {\n ensureAdmin();\n ensureNonzeroAddress(vault_);\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n\n vaiVaultAddress = vault_;\n releaseStartBlock = releaseStartBlock_;\n minReleaseAmount = minReleaseAmount_;\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPrimeToken(IPrime _prime) external returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(_prime));\n\n IPrime oldPrime = prime;\n prime = _prime;\n emit NewPrimeToken(oldPrime, _prime);\n\n return uint(Error.NO_ERROR);\n }\n\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\n * borrows in the market may be liquidated regardless of the account liquidity\n * @dev Allows a privileged role to set enable/disable forced liquidations\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n ensureAllowed(\"_setForcedLiquidation(address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n }\n isForcedLiquidationEnabled[address(vTokenBorrowed)] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { FacetBase, VToken } from \"./FacetBase.sol\";\n\n/**\n * @title XVSRewardsHelper\n * @author Venus\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\n */\ncontract XVSRewardsHelper is FacetBase {\n /// @notice Emitted when XVS is distributed to a borrower\n event DistributedBorrowerVenus(\n VToken indexed vToken,\n address indexed borrower,\n uint256 venusDelta,\n uint256 venusBorrowIndex\n );\n\n /// @notice Emitted when XVS is distributed to a supplier\n event DistributedSupplierVenus(\n VToken indexed vToken,\n address indexed supplier,\n uint256 venusDelta,\n uint256 venusSupplyIndex\n );\n\n /**\n * @notice Accrue XVS to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n */\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\n if (deltaBlocks != 0 && borrowSpeed != 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \"224\");\n borrowState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n borrowState.block = blockNumber;\n }\n }\n\n /**\n * @notice Accrue XVS to the market by updating the supply index\n * @param vToken The market whose supply index to update\n */\n function updateVenusSupplyIndex(address vToken) internal {\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n uint256 supplySpeed = venusSupplySpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\n if (deltaBlocks != 0 && supplySpeed != 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \"224\");\n supplyState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n supplyState.block = blockNumber;\n }\n }\n\n /**\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute XVS to\n */\n function distributeSupplierVenus(address vToken, address supplier) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 supplyIndex = venusSupplyState[vToken].index;\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\n // Update supplier's index to the current index since we are distributing accrued XVS\n venusSupplierIndex[vToken][supplier] = supplyIndex;\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n // Multiply of supplierTokens and supplierDelta\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\n // Addition of supplierAccrued and supplierDelta\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\n }\n\n /**\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute XVS to\n */\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 borrowIndex = venusBorrowState[vToken].index;\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\n // Update borrowers's index to the current index since we are distributing accrued XVS\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\n }\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\npragma experimental ABIEncoderV2;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n function diamondCut(FacetCut[] calldata _diamondCut) external;\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IMarketFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\n\ninterface IMarketFacet {\n function isComptroller() external pure returns (bool);\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function checkMembership(address account, VToken vToken) external view returns (bool);\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n function _supportMarket(VToken vToken) external returns (uint256);\n\n function getAssetsIn(address account) external view returns (VToken[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function updateDelegate(address delegate, bool allowBorrows) external;\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IPolicyFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\n\ninterface IPolicyFacet {\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\n\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\n\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\n\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount\n ) external returns (uint256);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount,\n uint256 borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount,\n uint256 seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external returns (uint256);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external;\n\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256);\n\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\n\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256);\n\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external;\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { ComptrollerV14Storage } from \"../../ComptrollerStorage.sol\";\n\ninterface IRewardFacet {\n function claimVenus(address holder) external;\n\n function claimVenus(address holder, VToken[] calldata vTokens) external;\n\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\n\n function claimVenusAsCollateral(address holder) external;\n\n function _grantXVS(address recipient, uint256 amount) external;\n\n function getXVSAddress() external pure returns (address);\n\n function getXVSVTokenAddress() external pure returns (address);\n\n function actionPaused(address market, ComptrollerV14Storage.Action action) external view returns (bool);\n\n function claimVenus(\n address[] calldata holders,\n VToken[] calldata vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) external;\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\n\nimport { PriceOracle } from \"../../../Oracle/PriceOracle.sol\";\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { ComptrollerV14Storage } from \"../../ComptrollerStorage.sol\";\nimport { VAIControllerInterface } from \"../../../Tokens/VAI/VAIController.sol\";\nimport { ComptrollerLensInterface } from \"../../../Comptroller/ComptrollerLensInterface.sol\";\nimport { IPrime } from \"../../../Tokens/Prime/IPrime.sol\";\n\ninterface ISetterFacet {\n function _setPriceOracle(PriceOracle newOracle) external returns (uint256);\n\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\n\n function _setCollateralFactor(VToken vToken, uint256 newCollateralFactorMantissa) external returns (uint256);\n\n function _setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256);\n\n function _setLiquidatorContract(address newLiquidatorContract_) external;\n\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\n\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setProtocolPaused(bool state) external returns (bool);\n\n function _setActionsPaused(\n address[] calldata markets,\n ComptrollerV14Storage.Action[] calldata actions,\n bool paused\n ) external;\n\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\n\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\n\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\n\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256);\n\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external returns (uint256);\n\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\n\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\n\n function _setForcedLiquidation(address vToken, bool enable) external;\n\n function _setPrimeToken(IPrime _prime) external returns (uint);\n}\n" + }, + "contracts/Comptroller/Unitroller.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./ComptrollerStorage.sol\";\nimport \"../Utils/ErrorReporter.sol\";\n\n/**\n * @title ComptrollerCore\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\n * VTokens should reference this contract as their comptroller.\n */\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\n /**\n * @notice Emitted when pendingComptrollerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor() public {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public returns (uint) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldImplementation = comptrollerImplementation;\n address oldPendingImplementation = pendingComptrollerImplementation;\n\n comptrollerImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = address(0);\n\n emit NewImplementation(oldImplementation, comptrollerImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\n // Check caller = admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n }\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n function() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/Governance/VTreasury.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Utils/IBEP20.sol\";\nimport \"../Utils/SafeBEP20.sol\";\nimport \"../Utils/Ownable.sol\";\n\n/**\n * @title VTreasury\n * @author Venus\n * @notice Protocol treasury that holds tokens owned by Venus\n */\ncontract VTreasury is Ownable {\n using SafeMath for uint256;\n using SafeBEP20 for IBEP20;\n\n // WithdrawTreasuryBEP20 Event\n event WithdrawTreasuryBEP20(address tokenAddress, uint256 withdrawAmount, address withdrawAddress);\n\n // WithdrawTreasuryBNB Event\n event WithdrawTreasuryBNB(uint256 withdrawAmount, address withdrawAddress);\n\n /**\n * @notice To receive BNB\n */\n function() external payable {}\n\n /**\n * @notice Withdraw Treasury BEP20 Tokens, Only owner call it\n * @param tokenAddress The address of treasury token\n * @param withdrawAmount The withdraw amount to owner\n * @param withdrawAddress The withdraw address\n */\n function withdrawTreasuryBEP20(\n address tokenAddress,\n uint256 withdrawAmount,\n address withdrawAddress\n ) external onlyOwner {\n uint256 actualWithdrawAmount = withdrawAmount;\n // Get Treasury Token Balance\n uint256 treasuryBalance = IBEP20(tokenAddress).balanceOf(address(this));\n\n // Check Withdraw Amount\n if (withdrawAmount > treasuryBalance) {\n // Update actualWithdrawAmount\n actualWithdrawAmount = treasuryBalance;\n }\n\n // Transfer BEP20 Token to withdrawAddress\n IBEP20(tokenAddress).safeTransfer(withdrawAddress, actualWithdrawAmount);\n\n emit WithdrawTreasuryBEP20(tokenAddress, actualWithdrawAmount, withdrawAddress);\n }\n\n /**\n * @notice Withdraw Treasury BNB, Only owner call it\n * @param withdrawAmount The withdraw amount to owner\n * @param withdrawAddress The withdraw address\n */\n function withdrawTreasuryBNB(uint256 withdrawAmount, address payable withdrawAddress) external payable onlyOwner {\n uint256 actualWithdrawAmount = withdrawAmount;\n // Get Treasury BNB Balance\n uint256 bnbBalance = address(this).balance;\n\n // Check Withdraw Amount\n if (withdrawAmount > bnbBalance) {\n // Update actualWithdrawAmount\n actualWithdrawAmount = bnbBalance;\n }\n // Transfer BNB to withdrawAddress\n withdrawAddress.transfer(actualWithdrawAmount);\n\n emit WithdrawTreasuryBNB(actualWithdrawAmount, withdrawAddress);\n }\n}\n" + }, + "contracts/InterestRateModels/InterestRateModel.sol": { + "content": "pragma solidity ^0.5.16;\n\n/**\n * @title Venus's InterestRateModel Interface\n * @author Venus\n */\ncontract InterestRateModel {\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\n bool public constant isInterestRateModel = true;\n\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amnount of reserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uint cash, uint borrows, uint reserves) external view returns (uint);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amnount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint cash,\n uint borrows,\n uint reserves,\n uint reserveFactorMantissa\n ) external view returns (uint);\n}\n" + }, + "contracts/InterestRateModels/JumpRateModel.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Utils/SafeMath.sol\";\nimport \"./InterestRateModel.sol\";\n\n/**\n * @title Venus's JumpRateModel Contract\n * @author Venus\n */\ncontract JumpRateModel is InterestRateModel {\n using SafeMath for uint;\n\n event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock, uint jumpMultiplierPerBlock, uint kink);\n\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint public constant blocksPerYear = (60 * 60 * 24 * 365) / 3; // (assuming 3s blocks)\n\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint public multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint public baseRatePerBlock;\n\n /**\n * @notice The multiplierPerBlock after hitting a specified utilization point\n */\n uint public jumpMultiplierPerBlock;\n\n /**\n * @notice The utilization point at which the jump multiplier is applied\n */\n uint public kink;\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18)\n * @param jumpMultiplierPerYear The multiplierPerBlock after hitting a specified utilization point\n * @param kink_ The utilization point at which the jump multiplier is applied\n */\n constructor(uint baseRatePerYear, uint multiplierPerYear, uint jumpMultiplierPerYear, uint kink_) public {\n baseRatePerBlock = baseRatePerYear.div(blocksPerYear);\n multiplierPerBlock = multiplierPerYear.div(blocksPerYear);\n jumpMultiplierPerBlock = jumpMultiplierPerYear.div(blocksPerYear);\n kink = kink_;\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock, jumpMultiplierPerBlock, kink);\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @return The utilization rate as a mantissa between [0, 1e18]\n */\n function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) {\n // Utilization rate is 0 when there are no borrows\n if (borrows == 0) {\n return 0;\n }\n\n return borrows.mul(1e18).div(cash.add(borrows).sub(reserves));\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getBorrowRate(uint cash, uint borrows, uint reserves) public view returns (uint) {\n uint util = utilizationRate(cash, borrows, reserves);\n\n if (util <= kink) {\n return util.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);\n } else {\n uint normalRate = kink.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);\n uint excessUtil = util.sub(kink);\n return excessUtil.mul(jumpMultiplierPerBlock).div(1e18).add(normalRate);\n }\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @return The supply rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getSupplyRate(\n uint cash,\n uint borrows,\n uint reserves,\n uint reserveFactorMantissa\n ) public view returns (uint) {\n uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa);\n uint borrowRate = getBorrowRate(cash, borrows, reserves);\n uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18);\n return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18);\n }\n}\n" + }, + "contracts/InterestRateModels/WhitePaperInterestRateModel.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Utils/SafeMath.sol\";\nimport \"./InterestRateModel.sol\";\n\n/**\n * @title Venus's WhitePaperInterestRateModel Contract\n * @author Venus\n * @notice The parameterized model described in section 2.4 of the original Venus Protocol whitepaper\n */\ncontract WhitePaperInterestRateModel is InterestRateModel {\n using SafeMath for uint;\n\n event NewInterestParams(uint baseRatePerBlock, uint multiplierPerBlock);\n\n /**\n * @notice The approximate number of blocks per year that is assumed by the interest rate model\n */\n uint public constant blocksPerYear = (60 * 60 * 24 * 365) / 3; // (assuming 3s blocks)\n\n /**\n * @notice The multiplier of utilization rate that gives the slope of the interest rate\n */\n uint public multiplierPerBlock;\n\n /**\n * @notice The base interest rate which is the y-intercept when utilization rate is 0\n */\n uint public baseRatePerBlock;\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear The approximate target base APR, as a mantissa (scaled by 1e18)\n * @param multiplierPerYear The rate of increase in interest rate wrt utilization (scaled by 1e18)\n */\n constructor(uint baseRatePerYear, uint multiplierPerYear) public {\n baseRatePerBlock = baseRatePerYear.div(blocksPerYear);\n multiplierPerBlock = multiplierPerYear.div(blocksPerYear);\n\n emit NewInterestParams(baseRatePerBlock, multiplierPerBlock);\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market (currently unused)\n * @return The utilization rate as a mantissa between [0, 1e18]\n */\n function utilizationRate(uint cash, uint borrows, uint reserves) public pure returns (uint) {\n // Utilization rate is 0 when there are no borrows\n if (borrows == 0) {\n return 0;\n }\n\n return borrows.mul(1e18).div(cash.add(borrows).sub(reserves));\n }\n\n /**\n * @notice Calculates the current borrow rate per block, with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @return The borrow rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getBorrowRate(uint cash, uint borrows, uint reserves) public view returns (uint) {\n uint ur = utilizationRate(cash, borrows, reserves);\n return ur.mul(multiplierPerBlock).div(1e18).add(baseRatePerBlock);\n }\n\n /**\n * @notice Calculates the current supply rate per block\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @return The supply rate percentage per block as a mantissa (scaled by 1e18)\n */\n function getSupplyRate(\n uint cash,\n uint borrows,\n uint reserves,\n uint reserveFactorMantissa\n ) public view returns (uint) {\n uint oneMinusReserveFactor = uint(1e18).sub(reserveFactorMantissa);\n uint borrowRate = getBorrowRate(cash, borrows, reserves);\n uint rateToPool = borrowRate.mul(oneMinusReserveFactor).div(1e18);\n return utilizationRate(cash, borrows, reserves).mul(rateToPool).div(1e18);\n }\n}\n" + }, + "contracts/Lens/ComptrollerLens.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"../Tokens/VTokens/VBep20.sol\";\nimport \"../Tokens/VTokens/VToken.sol\";\nimport \"../Tokens/EIP20Interface.sol\";\nimport \"../Oracle/PriceOracle.sol\";\nimport \"../Utils/ErrorReporter.sol\";\nimport \"../Comptroller/ComptrollerInterface.sol\";\nimport \"../Comptroller/ComptrollerLensInterface.sol\";\nimport \"../Tokens/VAI/VAIControllerInterface.sol\";\n\n/**\n * @title ComptrollerLens Contract\n * @author Venus\n * @notice The ComptrollerLens contract has functions to get the number of tokens that\n * can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\n */\ncontract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, ExponentialNoError {\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountLiquidityLocalVars {\n uint sumCollateral;\n uint sumBorrowPlusEffects;\n uint vTokenBalance;\n uint borrowBalance;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp collateralFactor;\n Exp exchangeRate;\n Exp oraclePrice;\n Exp tokensToDenom;\n }\n\n /**\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\n * @param comptroller Address of comptroller\n * @param vTokenBorrowed Address of the borrowed vToken\n * @param vTokenCollateral Address of collateral for the borrow\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\n * @return A tuple of error code, and tokens to seize\n */\n function liquidateCalculateSeizeTokens(\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(\n VToken(vTokenBorrowed)\n );\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(\n VToken(vTokenCollateral)\n );\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(\n Exp({ mantissa: ComptrollerInterface(comptroller).liquidationIncentiveMantissa() }),\n Exp({ mantissa: priceBorrowedMantissa })\n );\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /**\n * @notice Computes the number of VAI tokens to be seized in a liquidation event\n * @param comptroller Address of comptroller\n * @param vTokenCollateral Address of collateral for vToken\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of the total borrowed amount\n * @return A tuple of error code, and tokens to seize\n */\n function liquidateVAICalculateSeizeTokens(\n address comptroller,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa = 1e18; // Note: this is VAI\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(\n VToken(vTokenCollateral)\n );\n if (priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint seizeTokens;\n Exp memory numerator;\n Exp memory denominator;\n Exp memory ratio;\n\n numerator = mul_(\n Exp({ mantissa: ComptrollerInterface(comptroller).liquidationIncentiveMantissa() }),\n Exp({ mantissa: priceBorrowedMantissa })\n );\n denominator = mul_(Exp({ mantissa: priceCollateralMantissa }), Exp({ mantissa: exchangeRateMantissa }));\n ratio = div_(numerator, denominator);\n\n seizeTokens = mul_ScalarTruncate(ratio, actualRepayAmount);\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /**\n * @notice Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow\n * A snapshot of the account is taken and the total borrow amount of the account is calculated\n * @param comptroller Address of comptroller\n * @param account Address of the borrowed vToken\n * @param vTokenModify Address of collateral for vToken\n * @param redeemTokens Number of vTokens being redeemed\n * @param borrowAmount Amount borrowed\n * @return Returns a tuple of error code, liquidity, and shortfall\n */\n function getHypotheticalAccountLiquidity(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount\n ) external view returns (uint, uint, uint) {\n AccountLiquidityLocalVars memory vars; // Holds all our calculation results\n uint oErr;\n\n // For each asset the account is in\n VToken[] memory assets = ComptrollerInterface(comptroller).getAssetsIn(account);\n uint assetsCount = assets.length;\n for (uint i = 0; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(\n account\n );\n if (oErr != 0) {\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\n return (uint(Error.SNAPSHOT_ERROR), 0, 0);\n }\n (, uint collateralFactorMantissa) = ComptrollerInterface(comptroller).markets(address(asset));\n vars.collateralFactor = Exp({ mantissa: collateralFactorMantissa });\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n // Get the normalized price of the asset\n vars.oraclePriceMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(asset);\n if (vars.oraclePriceMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0, 0);\n }\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\n\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice);\n\n // sumCollateral += tokensToDenom * vTokenBalance\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.vTokenBalance, vars.sumCollateral);\n\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.oraclePrice,\n vars.borrowBalance,\n vars.sumBorrowPlusEffects\n );\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.tokensToDenom,\n redeemTokens,\n vars.sumBorrowPlusEffects\n );\n\n // borrow effect\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.oraclePrice,\n borrowAmount,\n vars.sumBorrowPlusEffects\n );\n }\n }\n\n VAIControllerInterface vaiController = ComptrollerInterface(comptroller).vaiController();\n\n if (address(vaiController) != address(0)) {\n vars.sumBorrowPlusEffects = add_(vars.sumBorrowPlusEffects, vaiController.getVAIRepayAmount(account));\n }\n\n // These are safe, as the underflow condition is checked first\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\n return (uint(Error.NO_ERROR), vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\n } else {\n return (uint(Error.NO_ERROR), 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\n }\n }\n}\n" + }, + "contracts/Lens/SnapshotLens.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"../Tokens/VTokens/VToken.sol\";\nimport \"../Utils/SafeMath.sol\";\nimport \"../Comptroller/ComptrollerInterface.sol\";\nimport \"../Tokens/EIP20Interface.sol\";\nimport \"../Tokens/VTokens/VBep20.sol\";\n\ncontract SnapshotLens is ExponentialNoError {\n using SafeMath for uint256;\n\n struct AccountSnapshot {\n address account;\n string assetName;\n address vTokenAddress;\n address underlyingAssetAddress;\n uint256 supply;\n uint256 supplyInUsd;\n uint256 collateral;\n uint256 borrows;\n uint256 borrowsInUsd;\n uint256 assetPrice;\n uint256 accruedInterest;\n uint vTokenDecimals;\n uint underlyingDecimals;\n uint exchangeRate;\n bool isACollateral;\n }\n\n /** Snapshot calculation **/\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account snapshot.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountSnapshotLocalVars {\n uint collateral;\n uint vTokenBalance;\n uint borrowBalance;\n uint borrowsInUsd;\n uint balanceOfUnderlying;\n uint supplyInUsd;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp collateralFactor;\n Exp exchangeRate;\n Exp oraclePrice;\n Exp tokensToDenom;\n bool isACollateral;\n }\n\n function getAccountSnapshot(\n address payable account,\n address comptrollerAddress\n ) public returns (AccountSnapshot[] memory) {\n // For each asset the account is in\n VToken[] memory assets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n AccountSnapshot[] memory accountSnapshots = new AccountSnapshot[](assets.length);\n for (uint256 i = 0; i < assets.length; ++i) {\n accountSnapshots[i] = getAccountSnapshot(account, comptrollerAddress, assets[i]);\n }\n return accountSnapshots;\n }\n\n function isACollateral(address account, address asset, address comptrollerAddress) public view returns (bool) {\n VToken[] memory assetsAsCollateral = ComptrollerInterface(comptrollerAddress).getAssetsIn(account);\n for (uint256 j = 0; j < assetsAsCollateral.length; ++j) {\n if (address(assetsAsCollateral[j]) == asset) {\n return true;\n }\n }\n\n return false;\n }\n\n function getAccountSnapshot(\n address payable account,\n address comptrollerAddress,\n VToken vToken\n ) public returns (AccountSnapshot memory) {\n AccountSnapshotLocalVars memory vars; // Holds all our calculation results\n uint oErr;\n\n // Read the balances and exchange rate from the vToken\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = vToken.getAccountSnapshot(account);\n require(oErr == 0, \"Snapshot Error\");\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n (, uint collateralFactorMantissa) = ComptrollerInterface(comptrollerAddress).markets(address(vToken));\n vars.collateralFactor = Exp({ mantissa: collateralFactorMantissa });\n\n // Get the normalized price of the asset\n vars.oraclePriceMantissa = ComptrollerInterface(comptrollerAddress).oracle().getUnderlyingPrice(vToken);\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\n\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice);\n\n //Collateral = tokensToDenom * vTokenBalance\n vars.collateral = mul_ScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\n\n vars.balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n vars.supplyInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.balanceOfUnderlying);\n\n vars.borrowsInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.borrowBalance);\n\n address underlyingAssetAddress;\n uint underlyingDecimals;\n\n if (compareStrings(vToken.symbol(), \"vBNB\")) {\n underlyingAssetAddress = address(0);\n underlyingDecimals = 18;\n } else {\n VBep20 vBep20 = VBep20(address(vToken));\n underlyingAssetAddress = vBep20.underlying();\n underlyingDecimals = EIP20Interface(vBep20.underlying()).decimals();\n }\n\n vars.isACollateral = isACollateral(account, address(vToken), comptrollerAddress);\n\n return\n AccountSnapshot({\n account: account,\n assetName: vToken.name(),\n vTokenAddress: address(vToken),\n underlyingAssetAddress: underlyingAssetAddress,\n supply: vars.balanceOfUnderlying,\n supplyInUsd: vars.supplyInUsd,\n collateral: vars.collateral,\n borrows: vars.borrowBalance,\n borrowsInUsd: vars.borrowsInUsd,\n assetPrice: vars.oraclePriceMantissa,\n accruedInterest: vToken.borrowIndex(),\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n exchangeRate: vToken.exchangeRateCurrent(),\n isACollateral: vars.isACollateral\n });\n }\n\n // utilities\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}\n" + }, + "contracts/Lens/VenusLens.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"../Tokens/VTokens/VBep20.sol\";\nimport \"../Tokens/VTokens/VToken.sol\";\nimport \"../Oracle/PriceOracle.sol\";\nimport \"../Tokens/EIP20Interface.sol\";\nimport \"../Tokens/XVS/XVS.sol\";\nimport \"../Comptroller/ComptrollerInterface.sol\";\nimport \"../Utils/SafeMath.sol\";\n\ncontract VenusLens is ExponentialNoError {\n using SafeMath for uint;\n\n /// @notice Blocks Per Day\n uint public constant BLOCKS_PER_DAY = 28800;\n\n struct VenusMarketState {\n uint224 index;\n uint32 block;\n }\n\n struct VTokenMetadata {\n address vToken;\n uint exchangeRateCurrent;\n uint supplyRatePerBlock;\n uint borrowRatePerBlock;\n uint reserveFactorMantissa;\n uint totalBorrows;\n uint totalReserves;\n uint totalSupply;\n uint totalCash;\n bool isListed;\n uint collateralFactorMantissa;\n address underlyingAssetAddress;\n uint vTokenDecimals;\n uint underlyingDecimals;\n uint venusSupplySpeed;\n uint venusBorrowSpeed;\n uint dailySupplyXvs;\n uint dailyBorrowXvs;\n }\n\n struct VTokenBalances {\n address vToken;\n uint balanceOf;\n uint borrowBalanceCurrent;\n uint balanceOfUnderlying;\n uint tokenBalance;\n uint tokenAllowance;\n }\n\n struct VTokenUnderlyingPrice {\n address vToken;\n uint underlyingPrice;\n }\n\n struct AccountLimits {\n VToken[] markets;\n uint liquidity;\n uint shortfall;\n }\n\n struct XVSBalanceMetadata {\n uint balance;\n uint votes;\n address delegate;\n }\n\n struct XVSBalanceMetadataExt {\n uint balance;\n uint votes;\n address delegate;\n uint allocated;\n }\n\n struct VenusVotes {\n uint blockNumber;\n uint votes;\n }\n\n struct ClaimVenusLocalVariables {\n uint totalRewards;\n uint224 borrowIndex;\n uint32 borrowBlock;\n uint224 supplyIndex;\n uint32 supplyBlock;\n }\n\n /**\n * @dev Struct for Pending Rewards for per market\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct for Reward of a single reward token.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /**\n * @notice Query the metadata of a vToken by its address\n * @param vToken The address of the vToken to fetch VTokenMetadata\n * @return VTokenMetadata struct with vToken supply and borrow information.\n */\n function vTokenMetadata(VToken vToken) public returns (VTokenMetadata memory) {\n uint exchangeRateCurrent = vToken.exchangeRateCurrent();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerInterface comptroller = ComptrollerInterface(comptrollerAddress);\n (bool isListed, uint collateralFactorMantissa) = comptroller.markets(address(vToken));\n address underlyingAssetAddress;\n uint underlyingDecimals;\n\n if (compareStrings(vToken.symbol(), \"vBNB\")) {\n underlyingAssetAddress = address(0);\n underlyingDecimals = 18;\n } else {\n VBep20 vBep20 = VBep20(address(vToken));\n underlyingAssetAddress = vBep20.underlying();\n underlyingDecimals = EIP20Interface(vBep20.underlying()).decimals();\n }\n\n uint venusSupplySpeedPerBlock = comptroller.venusSupplySpeeds(address(vToken));\n uint venusBorrowSpeedPerBlock = comptroller.venusBorrowSpeeds(address(vToken));\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlock: vToken.supplyRatePerBlock(),\n borrowRatePerBlock: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: isListed,\n collateralFactorMantissa: collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n venusSupplySpeed: venusSupplySpeedPerBlock,\n venusBorrowSpeed: venusBorrowSpeedPerBlock,\n dailySupplyXvs: venusSupplySpeedPerBlock.mul(BLOCKS_PER_DAY),\n dailyBorrowXvs: venusBorrowSpeedPerBlock.mul(BLOCKS_PER_DAY)\n });\n }\n\n /**\n * @notice Get VTokenMetadata for an array of vToken addresses\n * @param vTokens Array of vToken addresses to fetch VTokenMetadata\n * @return Array of structs with vToken supply and borrow information.\n */\n function vTokenMetadataAll(VToken[] calldata vTokens) external returns (VTokenMetadata[] memory) {\n uint vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint i = 0; i < vTokenCount; i++) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Get amount of XVS distributed daily to an account\n * @param account Address of account to fetch the daily XVS distribution\n * @param comptrollerAddress Address of the comptroller proxy\n * @return Amount of XVS distributed daily to an account\n */\n function getDailyXVS(address payable account, address comptrollerAddress) external returns (uint) {\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(comptrollerAddress);\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\n uint dailyXvsPerAccount = 0;\n\n for (uint i = 0; i < vTokens.length; i++) {\n VToken vToken = vTokens[i];\n if (!compareStrings(vToken.symbol(), \"vUST\") && !compareStrings(vToken.symbol(), \"vLUNA\")) {\n VTokenMetadata memory metaDataItem = vTokenMetadata(vToken);\n\n //get balanceOfUnderlying and borrowBalanceCurrent from vTokenBalance\n VTokenBalances memory vTokenBalanceInfo = vTokenBalances(vToken, account);\n\n VTokenUnderlyingPrice memory underlyingPriceResponse = vTokenUnderlyingPrice(vToken);\n uint underlyingPrice = underlyingPriceResponse.underlyingPrice;\n Exp memory underlyingPriceMantissa = Exp({ mantissa: underlyingPrice });\n\n //get dailyXvsSupplyMarket\n uint dailyXvsSupplyMarket = 0;\n uint supplyInUsd = mul_ScalarTruncate(underlyingPriceMantissa, vTokenBalanceInfo.balanceOfUnderlying);\n uint marketTotalSupply = (metaDataItem.totalSupply.mul(metaDataItem.exchangeRateCurrent)).div(1e18);\n uint marketTotalSupplyInUsd = mul_ScalarTruncate(underlyingPriceMantissa, marketTotalSupply);\n\n if (marketTotalSupplyInUsd > 0) {\n dailyXvsSupplyMarket = (metaDataItem.dailySupplyXvs.mul(supplyInUsd)).div(marketTotalSupplyInUsd);\n }\n\n //get dailyXvsBorrowMarket\n uint dailyXvsBorrowMarket = 0;\n uint borrowsInUsd = mul_ScalarTruncate(underlyingPriceMantissa, vTokenBalanceInfo.borrowBalanceCurrent);\n uint marketTotalBorrowsInUsd = mul_ScalarTruncate(underlyingPriceMantissa, metaDataItem.totalBorrows);\n\n if (marketTotalBorrowsInUsd > 0) {\n dailyXvsBorrowMarket = (metaDataItem.dailyBorrowXvs.mul(borrowsInUsd)).div(marketTotalBorrowsInUsd);\n }\n\n dailyXvsPerAccount += dailyXvsSupplyMarket + dailyXvsBorrowMarket;\n }\n }\n\n return dailyXvsPerAccount;\n }\n\n /**\n * @notice Get the current vToken balance (outstanding borrows) for an account\n * @param vToken Address of the token to check the balance of\n * @param account Account address to fetch the balance of\n * @return VTokenBalances with token balance information\n */\n function vTokenBalances(VToken vToken, address payable account) public returns (VTokenBalances memory) {\n uint balanceOf = vToken.balanceOf(account);\n uint borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint tokenBalance;\n uint tokenAllowance;\n\n if (compareStrings(vToken.symbol(), \"vBNB\")) {\n tokenBalance = account.balance;\n tokenAllowance = account.balance;\n } else {\n VBep20 vBep20 = VBep20(address(vToken));\n EIP20Interface underlying = EIP20Interface(vBep20.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\n }\n\n return\n VTokenBalances({\n vToken: address(vToken),\n balanceOf: balanceOf,\n borrowBalanceCurrent: borrowBalanceCurrent,\n balanceOfUnderlying: balanceOfUnderlying,\n tokenBalance: tokenBalance,\n tokenAllowance: tokenAllowance\n });\n }\n\n /**\n * @notice Get the current vToken balances (outstanding borrows) for all vTokens on an account\n * @param vTokens Addresses of the tokens to check the balance of\n * @param account Account address to fetch the balance of\n * @return VTokenBalances Array with token balance information\n */\n function vTokenBalancesAll(\n VToken[] calldata vTokens,\n address payable account\n ) external returns (VTokenBalances[] memory) {\n uint vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint i = 0; i < vTokenCount; i++) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Get the price for the underlying asset of a vToken\n * @param vToken address of the vToken\n * @return response struct with underlyingPrice info of vToken\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerInterface comptroller = ComptrollerInterface(address(vToken.comptroller()));\n PriceOracle priceOracle = comptroller.oracle();\n\n return\n VTokenUnderlyingPrice({ vToken: address(vToken), underlyingPrice: priceOracle.getUnderlyingPrice(vToken) });\n }\n\n /**\n * @notice Query the underlyingPrice of an array of vTokens\n * @param vTokens Array of vToken addresses\n * @return array of response structs with underlying price information of vTokens\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint i = 0; i < vTokenCount; i++) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Query the account liquidity and shortfall of an account\n * @param comptroller Address of comptroller proxy\n * @param account Address of the account to query\n * @return Struct with markets user has entered, liquidity, and shortfall of the account\n */\n function getAccountLimits(\n ComptrollerInterface comptroller,\n address account\n ) public view returns (AccountLimits memory) {\n (uint errorCode, uint liquidity, uint shortfall) = comptroller.getAccountLiquidity(account);\n require(errorCode == 0, \"account liquidity error\");\n\n return AccountLimits({ markets: comptroller.getAssetsIn(account), liquidity: liquidity, shortfall: shortfall });\n }\n\n /**\n * @notice Query the XVSBalance info of an account\n * @param xvs XVS contract address\n * @param account Account address\n * @return Struct with XVS balance and voter details\n */\n function getXVSBalanceMetadata(XVS xvs, address account) external view returns (XVSBalanceMetadata memory) {\n return\n XVSBalanceMetadata({\n balance: xvs.balanceOf(account),\n votes: uint256(xvs.getCurrentVotes(account)),\n delegate: xvs.delegates(account)\n });\n }\n\n /**\n * @notice Query the XVSBalance extended info of an account\n * @param xvs XVS contract address\n * @param comptroller Comptroller proxy contract address\n * @param account Account address\n * @return Struct with XVS balance and voter details and XVS allocation\n */\n function getXVSBalanceMetadataExt(\n XVS xvs,\n ComptrollerInterface comptroller,\n address account\n ) external returns (XVSBalanceMetadataExt memory) {\n uint balance = xvs.balanceOf(account);\n comptroller.claimVenus(account);\n uint newBalance = xvs.balanceOf(account);\n uint accrued = comptroller.venusAccrued(account);\n uint total = add_(accrued, newBalance, \"sum xvs total\");\n uint allocated = sub_(total, balance, \"sub allocated\");\n\n return\n XVSBalanceMetadataExt({\n balance: balance,\n votes: uint256(xvs.getCurrentVotes(account)),\n delegate: xvs.delegates(account),\n allocated: allocated\n });\n }\n\n /**\n * @notice Query the voting power for an account at a specific list of block numbers\n * @param xvs XVS contract address\n * @param account Address of the account\n * @param blockNumbers Array of blocks to query\n * @return Array of VenusVotes structs with block number and vote count\n */\n function getVenusVotes(\n XVS xvs,\n address account,\n uint32[] calldata blockNumbers\n ) external view returns (VenusVotes[] memory) {\n VenusVotes[] memory res = new VenusVotes[](blockNumbers.length);\n for (uint i = 0; i < blockNumbers.length; i++) {\n res[i] = VenusVotes({\n blockNumber: uint256(blockNumbers[i]),\n votes: uint256(xvs.getPriorVotes(account, blockNumbers[i]))\n });\n }\n return res;\n }\n\n /**\n * @dev Queries the current supply to calculate rewards for an account\n * @param supplyState VenusMarketState struct\n * @param vToken Address of a vToken\n * @param comptroller Address of the comptroller proxy\n */\n function updateVenusSupplyIndex(\n VenusMarketState memory supplyState,\n address vToken,\n ComptrollerInterface comptroller\n ) internal view {\n uint supplySpeed = comptroller.venusSupplySpeeds(vToken);\n uint blockNumber = block.number;\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint supplyTokens = VToken(vToken).totalSupply();\n uint venusAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(venusAccrued, supplyTokens) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: supplyState.index }), ratio);\n supplyState.index = safe224(index.mantissa, \"new index overflows\");\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n /**\n * @dev Queries the current borrow to calculate rewards for an account\n * @param borrowState VenusMarketState struct\n * @param vToken Address of a vToken\n * @param comptroller Address of the comptroller proxy\n */\n function updateVenusBorrowIndex(\n VenusMarketState memory borrowState,\n address vToken,\n Exp memory marketBorrowIndex,\n ComptrollerInterface comptroller\n ) internal view {\n uint borrowSpeed = comptroller.venusBorrowSpeeds(vToken);\n uint blockNumber = block.number;\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n uint borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint venusAccrued = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(venusAccrued, borrowAmount) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: borrowState.index }), ratio);\n borrowState.index = safe224(index.mantissa, \"new index overflows\");\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n /**\n * @dev Calculate available rewards for an account's supply\n * @param supplyState VenusMarketState struct\n * @param vToken Address of a vToken\n * @param supplier Address of the account supplying\n * @param comptroller Address of the comptroller proxy\n * @return Undistributed earned XVS from supplies\n */\n function distributeSupplierVenus(\n VenusMarketState memory supplyState,\n address vToken,\n address supplier,\n ComptrollerInterface comptroller\n ) internal view returns (uint) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({ mantissa: comptroller.venusSupplierIndex(vToken, supplier) });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\n supplierIndex.mantissa = comptroller.venusInitialIndex();\n }\n\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint supplierTokens = VToken(vToken).balanceOf(supplier);\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n\n /**\n * @dev Calculate available rewards for an account's borrows\n * @param borrowState VenusMarketState struct\n * @param vToken Address of a vToken\n * @param borrower Address of the account borrowing\n * @param marketBorrowIndex vToken Borrow index\n * @param comptroller Address of the comptroller proxy\n * @return Undistributed earned XVS from borrows\n */\n function distributeBorrowerVenus(\n VenusMarketState memory borrowState,\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex,\n ComptrollerInterface comptroller\n ) internal view returns (uint) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({ mantissa: comptroller.venusBorrowerIndex(vToken, borrower) });\n if (borrowerIndex.mantissa > 0) {\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n return 0;\n }\n\n /**\n * @notice Calculate the total XVS tokens pending and accrued by a user account\n * @param holder Account to query pending XVS\n * @param comptroller Address of the comptroller\n * @return Reward object contraining the totalRewards and pending rewards for each market\n */\n function pendingRewards(\n address holder,\n ComptrollerInterface comptroller\n ) external view returns (RewardSummary memory) {\n VToken[] memory vTokens = comptroller.getAllMarkets();\n ClaimVenusLocalVariables memory vars;\n RewardSummary memory rewardSummary;\n rewardSummary.distributorAddress = address(comptroller);\n rewardSummary.rewardTokenAddress = comptroller.getXVSAddress();\n rewardSummary.totalRewards = comptroller.venusAccrued(holder);\n rewardSummary.pendingRewards = new PendingReward[](vTokens.length);\n for (uint i; i < vTokens.length; ++i) {\n (vars.borrowIndex, vars.borrowBlock) = comptroller.venusBorrowState(address(vTokens[i]));\n VenusMarketState memory borrowState = VenusMarketState({\n index: vars.borrowIndex,\n block: vars.borrowBlock\n });\n\n (vars.supplyIndex, vars.supplyBlock) = comptroller.venusSupplyState(address(vTokens[i]));\n VenusMarketState memory supplyState = VenusMarketState({\n index: vars.supplyIndex,\n block: vars.supplyBlock\n });\n\n Exp memory borrowIndex = Exp({ mantissa: vTokens[i].borrowIndex() });\n\n PendingReward memory marketReward;\n marketReward.vTokenAddress = address(vTokens[i]);\n\n updateVenusBorrowIndex(borrowState, address(vTokens[i]), borrowIndex, comptroller);\n uint256 borrowReward = distributeBorrowerVenus(\n borrowState,\n address(vTokens[i]),\n holder,\n borrowIndex,\n comptroller\n );\n\n updateVenusSupplyIndex(supplyState, address(vTokens[i]), comptroller);\n uint256 supplyReward = distributeSupplierVenus(supplyState, address(vTokens[i]), holder, comptroller);\n\n marketReward.amount = add_(borrowReward, supplyReward);\n rewardSummary.pendingRewards[i] = marketReward;\n }\n return rewardSummary;\n }\n\n // utilities\n /**\n * @notice Compares if two strings are equal\n * @param a First string to compare\n * @param b Second string to compare\n * @return Boolean depending on if the strings are equal\n */\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}\n" + }, + "contracts/Lens/XVSStakingLens.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../XVSVault/XVSVault.sol\";\nimport \"../Utils/IBEP20.sol\";\n\ncontract XVSStakingLens {\n /**\n * @notice Get the XVS stake balance of an account\n * @param account The address of the account to check\n * @param xvsAddress The address of the XVSToken\n * @param xvsVaultProxyAddress The address of the XVSVaultProxy\n * @return stakedAmount The balance that user staked\n * @return pendingWithdrawalAmount pending withdrawal amount of user.\n */\n function getStakedData(\n address account,\n address xvsAddress,\n address xvsVaultProxyAddress\n ) external view returns (uint256 stakedAmount, uint256 pendingWithdrawalAmount) {\n XVSVault xvsVaultInstance = XVSVault(xvsVaultProxyAddress);\n uint256 poolLength = xvsVaultInstance.poolLength(xvsAddress);\n\n for (uint256 pid = 0; pid < poolLength; ++pid) {\n (IBEP20 token, , , , ) = xvsVaultInstance.poolInfos(xvsAddress, pid);\n if (address(token) == address(xvsAddress)) {\n // solhint-disable-next-line no-unused-vars\n (uint256 userAmount, uint256 userRewardDebt, uint256 userPendingWithdrawals) = xvsVaultInstance\n .getUserInfo(xvsAddress, pid, account);\n stakedAmount = userAmount;\n pendingWithdrawalAmount = userPendingWithdrawals;\n break;\n }\n }\n\n return (stakedAmount, pendingWithdrawalAmount);\n }\n}\n" + }, + "contracts/Oracle/PriceOracle.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VTokens/VToken.sol\";\n\ncontract PriceOracle {\n /// @notice Indicator that this is a PriceOracle contract (for inspection)\n bool public constant isPriceOracle = true;\n\n /**\n * @notice Get the underlying price of a vToken asset\n * @param vToken The vToken to get the underlying price of\n * @return The underlying asset price mantissa (scaled by 1e18).\n * Zero means the price is unavailable.\n */\n function getUnderlyingPrice(VToken vToken) external view returns (uint);\n}\n" + }, + "contracts/test/BEP20.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Utils/SafeMath.sol\";\n\n// Mock import\nimport { GovernorBravoDelegate } from \"@venusprotocol/governance-contracts/contracts/Governance/GovernorBravoDelegate.sol\";\n\ninterface BEP20Base {\n event Approval(address indexed owner, address indexed spender, uint256 value);\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n function totalSupply() external view returns (uint256);\n\n function allowance(address owner, address spender) external view returns (uint256);\n\n function approve(address spender, uint256 value) external returns (bool);\n\n function balanceOf(address who) external view returns (uint256);\n}\n\ncontract BEP20 is BEP20Base {\n function transfer(address to, uint256 value) external returns (bool);\n\n function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n\ncontract BEP20NS is BEP20Base {\n function transfer(address to, uint256 value) external;\n\n function transferFrom(address from, address to, uint256 value) external;\n}\n\n/**\n * @title Standard BEP20 token\n * @dev Implementation of the basic standard token.\n * See https://github.com/ethereum/EIPs/issues/20\n */\ncontract StandardToken is BEP20 {\n using SafeMath for uint256;\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 public totalSupply;\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) public {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external returns (bool) {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n\n function approve(address _spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\n/**\n * @title Non-Standard BEP20 token\n * @dev Version of BEP20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ncontract NonStandardToken is BEP20NS {\n using SafeMath for uint256;\n\n string public name;\n uint8 public decimals;\n string public symbol;\n uint256 public totalSupply;\n mapping(address => mapping(address => uint256)) public allowance;\n mapping(address => uint256) public balanceOf;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) public {\n totalSupply = _initialAmount;\n balanceOf[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n }\n\n function transfer(address dst, uint256 amount) external {\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n }\n\n function transferFrom(address src, address dst, uint256 amount) external {\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n }\n\n function approve(address _spender, uint256 amount) external returns (bool) {\n allowance[msg.sender][_spender] = amount;\n emit Approval(msg.sender, _spender, amount);\n return true;\n }\n}\n\ncontract BEP20Harness is StandardToken {\n // To support testing, we can specify addresses for which transferFrom should fail and return false\n mapping(address => bool) public failTransferFromAddresses;\n\n // To support testing, we allow the contract to always fail `transfer`.\n mapping(address => bool) public failTransferToAddresses;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) public StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {}\n\n function harnessSetFailTransferFromAddress(address src, bool _fail) public {\n failTransferFromAddresses[src] = _fail;\n }\n\n function harnessSetFailTransferToAddress(address dst, bool _fail) public {\n failTransferToAddresses[dst] = _fail;\n }\n\n function harnessSetBalance(address _account, uint _amount) public {\n balanceOf[_account] = _amount;\n }\n\n function transfer(address dst, uint256 amount) external returns (bool success) {\n // Added for testing purposes\n if (failTransferToAddresses[dst]) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success) {\n // Added for testing purposes\n if (failTransferFromAddresses[src]) {\n return false;\n }\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount, \"Insufficient allowance\");\n balanceOf[src] = balanceOf[src].sub(amount, \"Insufficient balance\");\n balanceOf[dst] = balanceOf[dst].add(amount, \"Balance overflow\");\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/ComptrollerHarness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./ComptrollerMock.sol\";\nimport \"../Oracle/PriceOracle.sol\";\nimport \"../Comptroller/Unitroller.sol\";\n\ncontract ComptrollerHarness is ComptrollerMock {\n address internal xvsAddress;\n address internal vXVSAddress;\n uint public blockNumber;\n\n constructor() public ComptrollerMock() {}\n\n function setVenusSupplyState(address vToken, uint224 index, uint32 blockNumber_) public {\n venusSupplyState[vToken].index = index;\n venusSupplyState[vToken].block = blockNumber_;\n }\n\n function setVenusBorrowState(address vToken, uint224 index, uint32 blockNumber_) public {\n venusBorrowState[vToken].index = index;\n venusBorrowState[vToken].block = blockNumber_;\n }\n\n function setVenusAccrued(address user, uint userAccrued) public {\n venusAccrued[user] = userAccrued;\n }\n\n function setXVSAddress(address xvsAddress_) public {\n xvsAddress = xvsAddress_;\n }\n\n function setXVSVTokenAddress(address vXVSAddress_) public {\n vXVSAddress = vXVSAddress_;\n }\n\n /**\n * @notice Set the amount of XVS distributed per block\n * @param venusRate_ The amount of XVS wei per block to distribute\n */\n function harnessSetVenusRate(uint venusRate_) public {\n venusRate = venusRate_;\n }\n\n /**\n * @notice Recalculate and update XVS speeds for all XVS markets\n */\n function harnessRefreshVenusSpeeds() public {\n VToken[] memory allMarkets_ = allMarkets;\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusSupplyIndex(address(vToken));\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n }\n\n Exp memory totalUtility = Exp({ mantissa: 0 });\n Exp[] memory utilities = new Exp[](allMarkets_.length);\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n if (venusSpeeds[address(vToken)] > 0) {\n Exp memory assetPrice = Exp({ mantissa: oracle.getUnderlyingPrice(vToken) });\n Exp memory utility = mul_(assetPrice, vToken.totalBorrows());\n utilities[i] = utility;\n totalUtility = add_(totalUtility, utility);\n }\n }\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets[i];\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(venusRate, div_(utilities[i], totalUtility)) : 0;\n setVenusSpeedInternal(vToken, newSpeed, newSpeed);\n }\n }\n\n function setVenusBorrowerIndex(address vToken, address borrower, uint index) public {\n venusBorrowerIndex[vToken][borrower] = index;\n }\n\n function setVenusSupplierIndex(address vToken, address supplier, uint index) public {\n venusSupplierIndex[vToken][supplier] = index;\n }\n\n function harnessDistributeAllBorrowerVenus(\n address vToken,\n address borrower,\n uint marketBorrowIndexMantissa\n ) public {\n distributeBorrowerVenus(vToken, borrower, Exp({ mantissa: marketBorrowIndexMantissa }));\n venusAccrued[borrower] = grantXVSInternal(borrower, venusAccrued[borrower], 0, false);\n }\n\n function harnessDistributeAllSupplierVenus(address vToken, address supplier) public {\n distributeSupplierVenus(vToken, supplier);\n venusAccrued[supplier] = grantXVSInternal(supplier, venusAccrued[supplier], 0, false);\n }\n\n function harnessUpdateVenusBorrowIndex(address vToken, uint marketBorrowIndexMantissa) public {\n updateVenusBorrowIndex(vToken, Exp({ mantissa: marketBorrowIndexMantissa }));\n }\n\n function harnessUpdateVenusSupplyIndex(address vToken) public {\n updateVenusSupplyIndex(vToken);\n }\n\n function harnessDistributeBorrowerVenus(address vToken, address borrower, uint marketBorrowIndexMantissa) public {\n distributeBorrowerVenus(vToken, borrower, Exp({ mantissa: marketBorrowIndexMantissa }));\n }\n\n function harnessDistributeSupplierVenus(address vToken, address supplier) public {\n distributeSupplierVenus(vToken, supplier);\n }\n\n function harnessTransferVenus(address user, uint userAccrued, uint threshold) public returns (uint) {\n if (userAccrued > 0 && userAccrued >= threshold) {\n return grantXVSInternal(user, userAccrued, 0, false);\n }\n return userAccrued;\n }\n\n function harnessAddVenusMarkets(address[] memory vTokens) public {\n for (uint i = 0; i < vTokens.length; i++) {\n // temporarily set venusSpeed to 1 (will be fixed by `harnessRefreshVenusSpeeds`)\n setVenusSpeedInternal(VToken(vTokens[i]), 1, 1);\n }\n }\n\n function harnessSetMintedVAIs(address user, uint amount) public {\n mintedVAIs[user] = amount;\n }\n\n function harnessFastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getVenusMarkets() public view returns (address[] memory) {\n uint m = allMarkets.length;\n uint n = 0;\n for (uint i = 0; i < m; i++) {\n if (venusSpeeds[address(allMarkets[i])] > 0) {\n n++;\n }\n }\n\n address[] memory venusMarkets = new address[](n);\n uint k = 0;\n for (uint i = 0; i < m; i++) {\n if (venusSpeeds[address(allMarkets[i])] > 0) {\n venusMarkets[k++] = address(allMarkets[i]);\n }\n }\n return venusMarkets;\n }\n\n function harnessSetReleaseStartBlock(uint startBlock) external {\n releaseStartBlock = startBlock;\n }\n\n function harnessAddVtoken(address vToken) external {\n markets[vToken] = Market({ isListed: true, isVenus: false, collateralFactorMantissa: 0 });\n }\n}\n\ncontract EchoTypesComptroller is UnitrollerAdminStorage {\n function stringy(string memory s) public pure returns (string memory) {\n return s;\n }\n\n function addresses(address a) public pure returns (address) {\n return a;\n }\n\n function booly(bool b) public pure returns (bool) {\n return b;\n }\n\n function listOInts(uint[] memory u) public pure returns (uint[] memory) {\n return u;\n }\n\n function reverty() public pure {\n require(false, \"gotcha sucka\");\n }\n\n function becomeBrains(address payable unitroller) public {\n Unitroller(unitroller)._acceptImplementation();\n }\n}\n" + }, + "contracts/test/ComptrollerMock.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Comptroller/Diamond/facets/MarketFacet.sol\";\nimport \"../Comptroller/Diamond/facets/PolicyFacet.sol\";\nimport \"../Comptroller/Diamond/facets/RewardFacet.sol\";\nimport \"../Comptroller/Diamond/facets/SetterFacet.sol\";\nimport \"../Comptroller/Unitroller.sol\";\n\n// This contract contains all methods of Comptroller implementation in different facets at one place for testing purpose\n// This contract does not have diamond functionality(i.e delegate call to facets methods)\ncontract ComptrollerMock is MarketFacet, PolicyFacet, RewardFacet, SetterFacet {\n constructor() public {\n admin = msg.sender;\n }\n\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/test/ComptrollerScenario.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./ComptrollerMock.sol\";\n\ncontract ComptrollerScenario is ComptrollerMock {\n uint public blockNumber;\n address public xvsAddress;\n address public vaiAddress;\n\n constructor() public ComptrollerMock() {}\n\n function setXVSAddress(address xvsAddress_) public {\n xvsAddress = xvsAddress_;\n }\n\n // function getXVSAddress() public view returns (address) {\n // return xvsAddress;\n // }\n\n function setVAIAddress(address vaiAddress_) public {\n vaiAddress = vaiAddress_;\n }\n\n function getVAIAddress() public view returns (address) {\n return vaiAddress;\n }\n\n function membershipLength(VToken vToken) public view returns (uint) {\n return accountAssets[address(vToken)].length;\n }\n\n function fastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n\n return blockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getVenusMarkets() public view returns (address[] memory) {\n uint m = allMarkets.length;\n uint n = 0;\n for (uint i = 0; i < m; i++) {\n if (markets[address(allMarkets[i])].isVenus) {\n n++;\n }\n }\n\n address[] memory venusMarkets = new address[](n);\n uint k = 0;\n for (uint i = 0; i < m; i++) {\n if (markets[address(allMarkets[i])].isVenus) {\n venusMarkets[k++] = address(allMarkets[i]);\n }\n }\n return venusMarkets;\n }\n\n function unlist(VToken vToken) public {\n markets[address(vToken)].isListed = false;\n }\n\n /**\n * @notice Recalculate and update XVS speeds for all XVS markets\n */\n function refreshVenusSpeeds() public {\n VToken[] memory allMarkets_ = allMarkets;\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusSupplyIndex(address(vToken));\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n }\n\n Exp memory totalUtility = Exp({ mantissa: 0 });\n Exp[] memory utilities = new Exp[](allMarkets_.length);\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n if (venusSpeeds[address(vToken)] > 0) {\n Exp memory assetPrice = Exp({ mantissa: oracle.getUnderlyingPrice(vToken) });\n Exp memory utility = mul_(assetPrice, vToken.totalBorrows());\n utilities[i] = utility;\n totalUtility = add_(totalUtility, utility);\n }\n }\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets[i];\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(venusRate, div_(utilities[i], totalUtility)) : 0;\n setVenusSpeedInternal(vToken, newSpeed, newSpeed);\n }\n }\n}\n" + }, + "contracts/test/DiamondHarness.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"../Comptroller/Diamond/Diamond.sol\";\n\ncontract DiamondHarness is Diamond {\n function getFacetAddress(bytes4 sig) public view returns (address) {\n address facet = _selectorToFacetAndPosition[sig].facetAddress;\n require(facet != address(0), \"Diamond: Function does not exist\");\n return facet;\n }\n}\n" + }, + "contracts/test/EvilToken.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./FaucetToken.sol\";\n\n/**\n * @title The Venus Evil Test Token\n * @author Venus\n * @notice A simple test token that fails certain operations\n */\ncontract EvilToken is FaucetToken {\n bool public fail;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) public FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n fail = true;\n }\n\n function setFail(bool _fail) external {\n fail = _fail;\n }\n\n function transfer(address dst, uint256 amount) external returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint256 amount) external returns (bool) {\n if (fail) {\n return false;\n }\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(amount);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/EvilXDelegator.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VTokens/VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20Delegator Contract\n * @notice VTokens which wrap an EIP-20 underlying and delegate to an implementation\n * @author Venus\n */\ncontract EvilXDelegator is VTokenInterface, VBep20Interface, VDelegatorInterface {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData The encoded args for becomeImplementation\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n ) public {\n // Creator of the contract is admin during initialization\n admin = msg.sender;\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(\n implementation_,\n abi.encodeWithSignature(\n \"initialize(address,address,address,uint256,string,string,uint8)\",\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n )\n );\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_, false, becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) public {\n require(msg.sender == admin, \"VBep20Delegator::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature(\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint256 mintAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"mint(uint256)\", mintAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mintBehalf(address receiver, uint256 mintAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"mintBehalf(address,uint256)\", receiver, mintAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint256 redeemTokens) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"redeem(uint256)\", redeemTokens));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"redeemUnderlying(uint256)\", redeemAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrow(uint256 borrowAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrow(uint256)\", borrowAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint256 repayAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"repayBorrow(uint256)\", repayAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"repayBorrowBehalf(address,uint256)\", borrower, repayAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"liquidateBorrow(address,uint256,address)\", borrower, repayAmount, vTokenCollateral)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint256 amount) external returns (bool) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"transfer(address,uint256)\", dst, amount));\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint256 amount) external returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"transferFrom(address,address,uint256)\", src, dst, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"approve(address,uint256)\", spender, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (-1 means infinite)\n */\n function allowance(address owner, address spender) external view returns (uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"allowance(address,address)\", owner, spender)\n );\n return abi.decode(data, (uint256));\n }\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 bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"balanceOf(address)\", owner));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"balanceOfUnderlying(address)\", owner));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view returns (uint256, uint256, uint256, uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"getAccountSnapshot(address)\", account)\n );\n return abi.decode(data, (uint256, uint256, uint256, uint256));\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"borrowRatePerBlock()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"supplyRatePerBlock()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"totalBorrowsCurrent()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrowBalanceCurrent(address)\", account));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view returns (uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"borrowBalanceStored(address)\", account)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"exchangeRateCurrent()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\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() public view returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"exchangeRateStored()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"getCash()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves.\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n function accrueInterest() public returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"accrueInterest()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"seize(address,address,uint256)\", liquidator, borrower, seizeTokens)\n );\n return abi.decode(data, (uint256));\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setPendingAdmin(address)\", newPendingAdmin)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setComptroller(address)\", newComptroller)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setReserveFactor(uint256 newReserveFactorMantissa) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setReserveFactor(uint256)\", newReserveFactorMantissa)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_acceptAdmin()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from admin\n * @param addAmount Amount of reserves to add\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint256 addAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_addReserves(uint256)\", addAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _reduceReserves(uint256 reduceAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_reduceReserves(uint256)\", reduceAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setInterestRateModel(address)\", newInterestRateModel)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n return returnData;\n }\n\n /**\n * @notice Delegates execution to the implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToImplementation(bytes memory data) public returns (bytes memory) {\n return delegateTo(implementation, data);\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n (bool success, bytes memory returnData) = address(this).staticcall(\n abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data)\n );\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n return abi.decode(returnData, (bytes));\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n */\n function() external payable {\n require(msg.value == 0, \"VBep20Delegator:fallback: cannot send value to fallback\");\n\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/test/EvilXToken.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VTokens/VBep20Immutable.sol\";\nimport \"../Tokens/VTokens/VBep20Delegator.sol\";\nimport \"../Tokens/VTokens/VBep20Delegate.sol\";\nimport \"./ComptrollerScenario.sol\";\nimport \"../Comptroller/ComptrollerInterface.sol\";\n\ncontract VBep20Scenario is VBep20Immutable {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n public\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\n// doTransferOut method of this token supposed to be compromised and contians malicious code which\n// can be used by attacker to compromise the protocol working.\ncontract EvilXToken is VBep20Delegate {\n event Log(string x, address y);\n event Log(string x, uint y);\n event LogLiquidity(uint liquidity);\n\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n address public comptrollerAddress;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function setComptrollerAddress(address _comptrollerAddress) external {\n comptrollerAddress = _comptrollerAddress;\n }\n\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function doTransferOut(address payable to, uint amount) internal {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n super.doTransferOut(to, amount);\n\n // Checking the Liquidity of the user after the tranfer.\n // solhint-disable-next-line no-unused-vars\n (uint errorCode, uint liquidity, uint shortfall) = ComptrollerInterface(comptrollerAddress).getAccountLiquidity(\n msg.sender\n );\n emit LogLiquidity(liquidity);\n return;\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessIncrementTotalBorrows(uint addtlBorrow_) public {\n totalBorrows = totalBorrows + addtlBorrow_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModel(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n}\n" + }, + "contracts/test/Fauceteer.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/EIP20NonStandardInterface.sol\";\n\n/**\n * @title Fauceteer\n * @author Venus\n * @notice First computer program to be part of The Giving Pledge\n */\ncontract Fauceteer {\n /**\n * @notice Drips some tokens to caller\n * @dev We send 0.01% of our tokens to the caller. Over time, the amount will tend toward and eventually reach zero.\n * @param token The token to drip. Note: if we have no balance in this token, function will revert.\n */\n function drip(EIP20NonStandardInterface token) public {\n uint tokenBalance = token.balanceOf(address(this));\n require(tokenBalance > 0, \"Fauceteer is empty\");\n token.transfer(msg.sender, tokenBalance / 10000); // 0.01%\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard BEP-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a compliant BEP-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant BEP-20, revert.\n revert(0, 0)\n }\n }\n\n require(success, \"Transfer returned false.\");\n }\n}\n" + }, + "contracts/test/FaucetToken.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./BEP20.sol\";\n\n/**\n * @title The Venus Faucet Test Token\n * @author Venus\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetToken is StandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) public StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {}\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Venus Faucet Test Token (non-standard)\n * @author Venus\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetNonStandardToken is NonStandardToken {\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol\n ) public NonStandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {}\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n\n/**\n * @title The Venus Faucet Re-Entrant Test Token\n * @author Venus\n * @notice A test token that is malicious and tries to re-enter callers\n */\ncontract FaucetTokenReEntrantHarness {\n using SafeMath for uint256;\n\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n string public name;\n string public symbol;\n uint8 public decimals;\n uint256 internal totalSupply_;\n mapping(address => mapping(address => uint256)) internal allowance_;\n mapping(address => uint256) internal balanceOf_;\n\n bytes public reEntryCallData;\n string public reEntryFun;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n bytes memory _reEntryCallData,\n string memory _reEntryFun\n ) public {\n totalSupply_ = _initialAmount;\n balanceOf_[msg.sender] = _initialAmount;\n name = _tokenName;\n symbol = _tokenSymbol;\n decimals = _decimalUnits;\n reEntryCallData = _reEntryCallData;\n reEntryFun = _reEntryFun;\n }\n\n modifier reEnter(string memory funName) {\n string memory _reEntryFun = reEntryFun;\n if (compareStrings(_reEntryFun, funName)) {\n reEntryFun = \"\"; // Clear re-entry fun\n (bool success, bytes memory returndata) = msg.sender.call(reEntryCallData);\n assembly {\n if eq(success, 0) {\n revert(add(returndata, 0x20), returndatasize())\n }\n }\n }\n\n _;\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b)));\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf_[_owner] += value;\n totalSupply_ += value;\n emit Transfer(address(this), _owner, value);\n }\n\n function totalSupply() public reEnter(\"totalSupply\") returns (uint256) {\n return totalSupply_;\n }\n\n function allowance(address owner, address spender) public reEnter(\"allowance\") returns (uint256 remaining) {\n return allowance_[owner][spender];\n }\n\n function approve(address spender, uint256 amount) public reEnter(\"approve\") returns (bool success) {\n _approve(msg.sender, spender, amount);\n return true;\n }\n\n function balanceOf(address owner) public reEnter(\"balanceOf\") returns (uint256 balance) {\n return balanceOf_[owner];\n }\n\n function transfer(address dst, uint256 amount) public reEnter(\"transfer\") returns (bool success) {\n _transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(\n address src,\n address dst,\n uint256 amount\n ) public reEnter(\"transferFrom\") returns (bool success) {\n _transfer(src, dst, amount);\n _approve(src, msg.sender, allowance_[src][msg.sender].sub(amount));\n return true;\n }\n\n function _approve(address owner, address spender, uint256 amount) internal {\n require(spender != address(0), \"sender should be valid address\");\n require(owner != address(0), \"owner should be valid address\");\n allowance_[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n function _transfer(address src, address dst, uint256 amount) internal {\n require(dst != address(0), \"dst should be valid address\");\n balanceOf_[src] = balanceOf_[src].sub(amount);\n balanceOf_[dst] = balanceOf_[dst].add(amount);\n emit Transfer(src, dst, amount);\n }\n}\n" + }, + "contracts/test/FeeToken.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./FaucetToken.sol\";\n\n/**\n * @title Fee Token\n * @author Venus\n * @notice A simple test token that charges fees on transfer. Used to mock USDT.\n */\ncontract FeeToken is FaucetToken {\n uint public basisPointFee;\n address public owner;\n\n constructor(\n uint256 _initialAmount,\n string memory _tokenName,\n uint8 _decimalUnits,\n string memory _tokenSymbol,\n uint _basisPointFee,\n address _owner\n ) public FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n basisPointFee = _basisPointFee;\n owner = _owner;\n }\n\n function transfer(address dst, uint amount) public returns (bool) {\n uint fee = amount.mul(basisPointFee).div(10000);\n uint net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[msg.sender] = balanceOf[msg.sender].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n emit Transfer(msg.sender, dst, amount);\n return true;\n }\n\n function transferFrom(address src, address dst, uint amount) public returns (bool) {\n uint fee = amount.mul(basisPointFee).div(10000);\n uint net = amount.sub(fee);\n balanceOf[owner] = balanceOf[owner].add(fee);\n balanceOf[src] = balanceOf[src].sub(amount);\n balanceOf[dst] = balanceOf[dst].add(net);\n allowance[src][msg.sender] = allowance[src][msg.sender].sub(amount);\n emit Transfer(src, dst, amount);\n return true;\n }\n}\n" + }, + "contracts/test/FixedPriceOracle.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Oracle/PriceOracle.sol\";\n\ncontract FixedPriceOracle is PriceOracle {\n uint public price;\n\n constructor(uint _price) public {\n price = _price;\n }\n\n function getUnderlyingPrice(VToken vToken) public view returns (uint) {\n vToken;\n return price;\n }\n\n function assetPrices(address asset) public view returns (uint) {\n asset;\n return price;\n }\n}\n" + }, + "contracts/test/InterestRateModelHarness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../InterestRateModels/InterestRateModel.sol\";\n\n/**\n * @title An Interest Rate Model for tests that can be instructed to return a failure instead of doing a calculation\n * @author Venus\n */\ncontract InterestRateModelHarness is InterestRateModel {\n uint public constant opaqueBorrowFailureCode = 20;\n bool public failBorrowRate;\n uint public borrowRate;\n\n constructor(uint borrowRate_) public {\n borrowRate = borrowRate_;\n }\n\n function setFailBorrowRate(bool failBorrowRate_) public {\n failBorrowRate = failBorrowRate_;\n }\n\n function setBorrowRate(uint borrowRate_) public {\n borrowRate = borrowRate_;\n }\n\n function getBorrowRate(uint _cash, uint _borrows, uint _reserves) public view returns (uint) {\n _cash; // unused\n _borrows; // unused\n _reserves; // unused\n require(!failBorrowRate, \"INTEREST_RATE_MODEL_ERROR\");\n return borrowRate;\n }\n\n function getSupplyRate(\n uint _cash,\n uint _borrows,\n uint _reserves,\n uint _reserveFactor\n ) external view returns (uint) {\n _cash; // unused\n _borrows; // unused\n _reserves; // unused\n return borrowRate * (1 - _reserveFactor);\n }\n}\n" + }, + "contracts/test/MockDeflationaryToken.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Utils/SafeMath.sol\";\n\ncontract DeflatingERC20 {\n using SafeMath for uint;\n\n string public constant name = \"Deflating Test Token\";\n string public constant symbol = \"DTT\";\n uint8 public constant decimals = 18;\n uint public totalSupply;\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n\n bytes32 public DOMAIN_SEPARATOR;\n // keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;\n mapping(address => uint) public nonces;\n\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n constructor(uint _totalSupply) public {\n uint chainId;\n assembly {\n chainId := chainid()\n }\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(bytes(\"1\")),\n chainId,\n address(this)\n )\n );\n _mint(msg.sender, _totalSupply);\n }\n\n function _mint(address to, uint value) internal {\n totalSupply = totalSupply.add(value);\n balanceOf[to] = balanceOf[to].add(value);\n emit Transfer(address(0), to, value);\n }\n\n function _burn(address from, uint value) internal {\n balanceOf[from] = balanceOf[from].sub(value);\n totalSupply = totalSupply.sub(value);\n emit Transfer(from, address(0), value);\n }\n\n function _approve(address owner, address spender, uint value) private {\n allowance[owner][spender] = value;\n emit Approval(owner, spender, value);\n }\n\n function _transfer(address from, address to, uint value) private {\n uint burnAmount = value / 100;\n _burn(from, burnAmount);\n uint transferAmount = value.sub(burnAmount);\n balanceOf[from] = balanceOf[from].sub(transferAmount);\n balanceOf[to] = balanceOf[to].add(transferAmount);\n emit Transfer(from, to, transferAmount);\n }\n\n function approve(address spender, uint value) external returns (bool) {\n _approve(msg.sender, spender, value);\n return true;\n }\n\n function transfer(address to, uint value) external returns (bool) {\n _transfer(msg.sender, to, value);\n return true;\n }\n\n function transferFrom(address from, address to, uint value) external returns (bool) {\n if (allowance[from][msg.sender] != uint(-1)) {\n allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);\n }\n _transfer(from, to, value);\n return true;\n }\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {\n require(deadline >= block.timestamp, \"EXPIRED\");\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNATURE\");\n _approve(owner, spender, value);\n }\n}\n" + }, + "contracts/test/MockVBNB.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VTokens/VToken.sol\";\n\n/**\n * @title Venus's vBNB Contract\n * @notice vToken which wraps BNB\n * @author Venus\n */\ncontract MockVBNB is VToken {\n /**\n * @notice Construct a new vBNB money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n */\n constructor(\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n ) public {\n // Creator of the contract is admin during initialization\n admin = msg.sender;\n\n initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Send BNB to VBNB to mint\n */\n function() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Reverts upon any failure\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits Mint event\n function mint() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, msg.sender, borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @dev Reverts upon any failure\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrow() external payable {\n (uint err, ) = repayBorrowInternal(msg.value);\n requireNoError(err, \"repayBorrow failed\");\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @dev Reverts upon any failure\n * @param borrower The account with the debt being payed off\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrowBehalf(address borrower) external payable {\n (uint err, ) = repayBorrowBehalfInternal(borrower, msg.value);\n requireNoError(err, \"repayBorrowBehalf failed\");\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @dev Reverts upon any failure\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n */\n // @custom:event Emit LiquidateBorrow event on success\n function liquidateBorrow(address borrower, VToken vTokenCollateral) external payable {\n (uint err, ) = liquidateBorrowInternal(borrower, msg.value, vTokenCollateral);\n requireNoError(err, \"liquidateBorrow failed\");\n }\n\n function setTotalReserves(uint totalReserves_) external payable {\n totalReserves = totalReserves_;\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Perform the actual transfer in, which is a no-op\n * @param from Address sending the BNB\n * @param amount Amount of BNB being sent\n * @return The actual amount of BNB transferred\n */\n function doTransferIn(address from, uint amount) internal returns (uint) {\n // Sanity checks\n require(msg.sender == from, \"sender mismatch\");\n require(msg.value == amount, \"value mismatch\");\n return amount;\n }\n\n function doTransferOut(address payable to, uint amount) internal {\n /* Send the BNB, with minimal gas and revert on failure */\n to.transfer(amount);\n }\n\n /**\n * @notice Gets balance of this contract in terms of BNB, before this message\n * @dev This excludes the value of the current message, if any\n * @return The quantity of BNB owned by this contract\n */\n function getCashPrior() internal view returns (uint) {\n (MathError err, uint startingBalance) = subUInt(address(this).balance, msg.value);\n require(err == MathError.NO_ERROR, \"cash prior math error\");\n return startingBalance;\n }\n\n function requireNoError(uint errCode, string memory message) internal pure {\n if (errCode == uint(Error.NO_ERROR)) {\n return;\n }\n\n bytes memory fullMessage = new bytes(bytes(message).length + 5);\n uint i;\n\n for (i = 0; i < bytes(message).length; i++) {\n fullMessage[i] = bytes(message)[i];\n }\n\n fullMessage[i + 0] = bytes1(uint8(32));\n fullMessage[i + 1] = bytes1(uint8(40));\n fullMessage[i + 2] = bytes1(uint8(48 + (errCode / 10)));\n fullMessage[i + 3] = bytes1(uint8(48 + (errCode % 10)));\n fullMessage[i + 4] = bytes1(uint8(41));\n\n require(errCode == uint(Error.NO_ERROR), string(fullMessage));\n }\n\n /**\n * @dev Function to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n */\n function getBlockNumber() internal view returns (uint) {\n return block.number;\n }\n\n /**\n * @notice Reduces reserves by transferring to admin\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReservesFresh(uint reduceAmount) internal returns (uint) {\n // totalReserves - reduceAmount\n uint totalReservesNew;\n\n // Check caller is admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.REDUCE_RESERVES_ADMIN_CHECK);\n }\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != getBlockNumber()) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (getCashPrior() < reduceAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew = totalReserves - reduceAmount;\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n doTransferOut(admin, reduceAmount);\n\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesReduced event\n function _reduceReserves(uint reduceAmount) external nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\n return _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n // @custom:event Emits AccrueInterest event\n function accrueInterest() public returns (uint) {\n /* Remember the initial block number */\n uint currentBlockNumber = getBlockNumber();\n uint accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return uint(Error.NO_ERROR);\n }\n\n /* Read the previous values out of storage */\n uint cashPrior = getCashPrior();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\n uint borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n require(borrowRateMantissa <= borrowRateMaxMantissa, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n require(mathErr == MathError.NO_ERROR, \"could not calculate block delta\");\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor;\n uint interestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return uint(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/test/SimplePriceOracle.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Oracle/PriceOracle.sol\";\nimport \"../Tokens/VTokens/VBep20.sol\";\n\ncontract SimplePriceOracle is PriceOracle {\n mapping(address => uint) internal prices;\n event PricePosted(address asset, uint previousPriceMantissa, uint requestedPriceMantissa, uint newPriceMantissa);\n\n function getUnderlyingPrice(VToken vToken) public view returns (uint) {\n if (compareStrings(vToken.symbol(), \"vBNB\")) {\n return 1e18;\n } else if (compareStrings(vToken.symbol(), \"VAI\")) {\n return prices[address(vToken)];\n } else {\n return prices[address(VBep20(address(vToken)).underlying())];\n }\n }\n\n function setUnderlyingPrice(VToken vToken, uint underlyingPriceMantissa) public {\n address asset = address(VBep20(address(vToken)).underlying());\n emit PricePosted(asset, prices[asset], underlyingPriceMantissa, underlyingPriceMantissa);\n prices[asset] = underlyingPriceMantissa;\n }\n\n function setDirectPrice(address asset, uint price) public {\n emit PricePosted(asset, prices[asset], price, price);\n prices[asset] = price;\n }\n\n // v1 price oracle interface for use as backing of proxy\n function assetPrices(address asset) external view returns (uint) {\n return prices[asset];\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}\n" + }, + "contracts/test/VAIControllerHarness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VAI/VAIController.sol\";\n\ncontract VAIControllerHarness is VAIController {\n address internal vaiAddress;\n uint public blockNumber;\n uint public blocksPerYear;\n\n constructor() public VAIController() {\n admin = msg.sender;\n }\n\n function setVenusVAIState(uint224 index, uint32 blockNumber_) public {\n venusVAIState.index = index;\n venusVAIState.block = blockNumber_;\n }\n\n function setVAIAddress(address vaiAddress_) public {\n vaiAddress = vaiAddress_;\n }\n\n function getVAIAddress() public view returns (address) {\n return vaiAddress;\n }\n\n function harnessRepayVAIFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayVAIFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateVAIFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateVAIFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessFastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function setBlocksPerYear(uint number) public {\n blocksPerYear = number;\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBlocksPerYear() public view returns (uint) {\n return blocksPerYear;\n }\n}\n" + }, + "contracts/test/VAIHarness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VAI/VAI.sol\";\n\ncontract VAIScenario is VAI {\n uint internal blockNumber = 100000;\n\n constructor(uint chainId) public VAI(chainId) {}\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetTotalSupply(uint _totalSupply) public {\n totalSupply = _totalSupply;\n }\n\n function harnessIncrementTotalSupply(uint addtlSupply_) public {\n totalSupply = totalSupply + addtlSupply_;\n }\n\n function harnessSetBalanceOf(address account, uint _amount) public {\n balanceOf[account] = _amount;\n }\n\n function allocateTo(address _owner, uint256 value) public {\n balanceOf[_owner] += value;\n totalSupply += value;\n emit Transfer(address(this), _owner, value);\n }\n}\n" + }, + "contracts/test/VBep20Harness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VTokens/VBep20Immutable.sol\";\nimport \"../Tokens/VTokens/VBep20Delegator.sol\";\nimport \"../Tokens/VTokens/VBep20Delegate.sol\";\nimport \"./ComptrollerScenario.sol\";\n\ncontract VBep20Harness is VBep20Immutable {\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n public\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function doTransferOut(address payable to, uint amount) internal {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n return super.doTransferOut(to, amount);\n }\n\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModel(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n}\n\ncontract VBep20Scenario is VBep20Immutable {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n public\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\ncontract VEvil is VBep20Scenario {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n public\n VBep20Scenario(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function evilSeize(VToken treasure, address liquidator, address borrower, uint seizeTokens) public returns (uint) {\n return treasure.seize(liquidator, borrower, seizeTokens);\n }\n}\n\ncontract VBep20DelegatorScenario is VBep20Delegator {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n )\n public\n VBep20Delegator(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n implementation_,\n becomeImplementationData\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n}\n\ncontract VBep20DelegateHarness is VBep20Delegate {\n event Log(string x, address y);\n event Log(string x, uint y);\n\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function doTransferOut(address payable to, uint amount) internal {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n return super.doTransferOut(to, amount);\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessIncrementTotalBorrows(uint addtlBorrow_) public {\n totalBorrows = totalBorrows + addtlBorrow_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModel newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModel(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n}\n\ncontract VBep20DelegateScenario is VBep20Delegate {\n constructor() public {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\ncontract VBep20DelegateScenarioExtra is VBep20DelegateScenario {\n function iHaveSpoken() public pure returns (string memory) {\n return \"i have spoken\";\n }\n\n function itIsTheWay() public {\n admin = address(1); // make a change to test effect\n }\n\n function babyYoda() public pure {\n revert(\"protect the baby\");\n }\n}\n" + }, + "contracts/test/VBep20MockDelegate.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/VTokens/VToken.sol\";\n\n/**\n * @title Venus's VBep20 Contract\n * @notice VTokens which wrap an EIP-20 underlying\n * @author Venus\n */\ncontract VBep20MockDelegate is VToken, VBep20Interface {\n address public implementation;\n uint internal blockNumber = 100000;\n\n /**\n * @notice Initialize the new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n // VToken initialize does the bulk of the work\n super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set underlying and sanity check it\n underlying = underlying_;\n EIP20Interface(underlying).totalSupply();\n }\n\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) public {\n // Shh -- currently unused\n data;\n\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _becomeImplementation\");\n }\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() public {\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _resignImplementation\");\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint mintAmount) external returns (uint) {\n (uint err, ) = mintInternal(mintAmount);\n return err;\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver the account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n (uint err, ) = mintBehalfInternal(receiver, mintAmount);\n return err;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, msg.sender, borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\n return err;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n (uint err, ) = liquidateBorrowInternal(borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount fo underlying token to add as reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint addAmount) external returns (uint) {\n return _addReservesInternal(addAmount);\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying tokens owned by this contract\n */\n function getCashPrior() internal view returns (uint) {\n EIP20Interface token = EIP20Interface(underlying);\n return token.balanceOf(address(this));\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\n * This will revert due to insufficient balance or insufficient allowance.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n *\n * Note: This wrapper safely handles non-standard BEP-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferIn(address from, uint amount) internal returns (uint) {\n EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying);\n uint balanceBefore = EIP20Interface(underlying).balanceOf(address(this));\n token.transferFrom(from, address(this), amount);\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard BEP-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a compliant BEP-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant BEP-20, revert.\n revert(0, 0)\n }\n }\n require(success, \"TOKEN_TRANSFER_IN_FAILED\");\n\n // Calculate the amount that was *actually* transferred\n uint balanceAfter = EIP20Interface(underlying).balanceOf(address(this));\n require(balanceAfter >= balanceBefore, \"TOKEN_TRANSFER_IN_OVERFLOW\");\n return balanceAfter - balanceBefore; // underflow already checked above, just subtract\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\n * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to\n * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified\n * it is >= amount, this should not revert in normal conditions.\n *\n * Note: This wrapper safely handles non-standard BEP-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferOut(address payable to, uint amount) internal {\n EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying);\n token.transfer(to, amount);\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard BEP-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a complaint BEP-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant BEP-20, revert.\n revert(0, 0)\n }\n }\n require(success, \"TOKEN_TRANSFER_OUT_FAILED\");\n }\n}\n" + }, + "contracts/test/VRTConverterHarness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../contracts/Tokens/VRT/VRTConverter.sol\";\n\ncontract VRTConverterHarness is VRTConverter {\n constructor() public VRTConverter() {\n admin = msg.sender;\n }\n\n function balanceOfUser() public view returns (uint256, address) {\n uint256 vrtBalanceOfUser = vrt.balanceOf(msg.sender);\n return (vrtBalanceOfUser, msg.sender);\n }\n\n function setConversionRatio(uint256 _conversionRatio) public onlyAdmin {\n conversionRatio = _conversionRatio;\n }\n\n function setConversionTimeline(uint256 _conversionStartTime, uint256 _conversionPeriod) public onlyAdmin {\n conversionStartTime = _conversionStartTime;\n conversionPeriod = _conversionPeriod;\n conversionEndTime = conversionStartTime.add(conversionPeriod);\n }\n\n function getXVSRedeemedAmount(uint256 vrtAmount) public view returns (uint256) {\n return vrtAmount.mul(conversionRatio).mul(xvsDecimalsMultiplier).div(1e18).div(vrtDecimalsMultiplier);\n }\n}\n" + }, + "contracts/test/VRTVaultHarness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../contracts/VRTVault/VRTVault.sol\";\n\ncontract VRTVaultHarness is VRTVault {\n uint public blockNumber;\n\n constructor() public VRTVault() {}\n\n function overrideInterestRatePerBlock(uint256 _interestRatePerBlock) public {\n interestRatePerBlock = _interestRatePerBlock;\n }\n\n function balanceOfUser() public view returns (uint256, address) {\n uint256 vrtBalanceOfUser = vrt.balanceOf(msg.sender);\n return (vrtBalanceOfUser, msg.sender);\n }\n\n function harnessFastForward(uint256 blocks) public returns (uint256) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint256 number) public {\n blockNumber = number;\n }\n\n function getBlockNumber() public view returns (uint256) {\n return blockNumber;\n }\n}\n" + }, + "contracts/test/XVSHarness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Tokens/XVS/XVS.sol\";\n\ncontract XVSScenario is XVS {\n constructor(address account) public XVS(account) {}\n\n function transferScenario(address[] calldata destinations, uint256 amount) external returns (bool) {\n for (uint i = 0; i < destinations.length; i++) {\n address dst = destinations[i];\n _transferTokens(msg.sender, dst, uint96(amount));\n }\n return true;\n }\n\n function transferFromScenario(address[] calldata froms, uint256 amount) external returns (bool) {\n for (uint i = 0; i < froms.length; i++) {\n address from = froms[i];\n _transferTokens(from, msg.sender, uint96(amount));\n }\n return true;\n }\n\n function generateCheckpoints(uint count, uint offset) external {\n for (uint i = 1 + offset; i <= count + offset; i++) {\n checkpoints[msg.sender][numCheckpoints[msg.sender]++] = Checkpoint(uint32(i), uint96(i));\n }\n }\n}\n" + }, + "contracts/test/XVSVaultScenario.sol": { + "content": "pragma solidity ^0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"../XVSVault/XVSVault.sol\";\n\ncontract XVSVaultScenario is XVSVault {\n using SafeMath for uint256;\n\n function pushOldWithdrawalRequest(\n UserInfo storage _user,\n WithdrawalRequest[] storage _requests,\n uint _amount,\n uint _lockedUntil\n ) internal {\n uint i = _requests.length;\n _requests.push(WithdrawalRequest(0, 0, 0));\n // Keep it sorted so that the first to get unlocked request is always at the end\n for (; i > 0 && _requests[i - 1].lockedUntil <= _lockedUntil; --i) {\n _requests[i] = _requests[i - 1];\n }\n _requests[i] = WithdrawalRequest(_amount, uint128(_lockedUntil), 0);\n _user.pendingWithdrawals = _user.pendingWithdrawals.add(_amount);\n }\n\n function requestOldWithdrawal(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant {\n _ensureValidPool(_rewardToken, _pid);\n require(_amount > 0, \"requested amount cannot be zero\");\n UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\n require(user.amount >= user.pendingWithdrawals.add(_amount), \"requested amount is invalid\");\n\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];\n uint lockedUntil = pool.lockPeriod.add(block.timestamp);\n\n pushOldWithdrawalRequest(user, requests, _amount, lockedUntil);\n\n // Update Delegate Amount\n if (_rewardToken == address(xvsAddress)) {\n _moveDelegates(delegates[msg.sender], address(0), uint96(_amount));\n }\n\n emit RequestedWithdrawal(msg.sender, _rewardToken, _pid, _amount);\n }\n\n function transferReward(address rewardToken, address user, uint256 amount) external {\n _transferReward(rewardToken, user, amount);\n }\n}\n" + }, + "contracts/test/XVSVestingHarness.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../contracts/Tokens/XVS/XVSVesting.sol\";\n\ncontract XVSVestingHarness is XVSVesting {\n address public constant ZERO_ADDRESS = 0x0000000000000000000000000000000000000000;\n\n constructor() public XVSVesting() {\n admin = msg.sender;\n }\n\n uint public blockNumber;\n\n function recoverXVS(address recoveryAddress) public payable {\n uint256 xvsBalance = xvs.balanceOf(address(this));\n xvs.safeTransferFrom(address(this), recoveryAddress, xvsBalance);\n }\n\n function overWriteVRTConversionAddress() public {\n vrtConversionAddress = ZERO_ADDRESS;\n }\n\n function computeWithdrawableAmount(\n uint256 amount,\n uint256 vestingStartTime,\n uint256 withdrawnAmount\n ) public view returns (uint256 vestedAmount, uint256 toWithdraw) {\n (vestedAmount, toWithdraw) = super.calculateWithdrawableAmount(amount, vestingStartTime, withdrawnAmount);\n return (vestedAmount, toWithdraw);\n }\n\n function computeVestedAmount(\n uint256 vestingAmount,\n uint256 vestingStartTime,\n uint256 currentTime\n ) public view returns (uint256) {\n return super.calculateVestedAmount(vestingAmount, vestingStartTime, currentTime);\n }\n\n function getVestingCount(address beneficiary) public view returns (uint256) {\n return vestings[beneficiary].length;\n }\n\n function getVestedAmount(address recipient) public view nonZeroAddress(recipient) returns (uint256) {\n VestingRecord[] memory vestingsOfRecipient = vestings[recipient];\n uint256 vestingCount = vestingsOfRecipient.length;\n uint256 totalVestedAmount = 0;\n uint256 currentTime = getCurrentTime();\n\n for (uint i = 0; i < vestingCount; i++) {\n VestingRecord memory vesting = vestingsOfRecipient[i];\n uint256 vestedAmount = calculateVestedAmount(vesting.amount, vesting.startTime, currentTime);\n totalVestedAmount = totalVestedAmount.add(vestedAmount);\n }\n\n return totalVestedAmount;\n }\n}\n" + }, + "contracts/Tokens/EIP20Interface.sol": { + "content": "pragma solidity ^0.5.16;\n\n/**\n * @title BEP 20 Token Standard Interface\n * https://eips.ethereum.org/EIPS/eip-20\n */\ninterface EIP20Interface {\n function name() external view returns (string memory);\n\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n\n /**\n * @notice Get the total number of tokens in circulation\n * @return The supply of tokens\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @notice Gets the balance of the specified address\n * @param owner The address from which the balance will be retrieved\n * @return balance\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success whether or not the transfer succeeded\n */\n function transfer(address dst, uint256 amount) external returns (bool success);\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return success whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return success whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external returns (bool success);\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return remaining The number of tokens allowed to be spent\n */\n function allowance(address owner, address spender) external view returns (uint256 remaining);\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n}\n" + }, + "contracts/Tokens/EIP20NonStandardInterface.sol": { + "content": "pragma solidity ^0.5.16;\n\n/**\n * @title EIP20NonStandardInterface\n * @dev Version of BEP20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ninterface EIP20NonStandardInterface {\n /**\n * @notice Get the total number of tokens in circulation\n * @return The supply of tokens\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @notice Gets the balance of the specified address\n * @param owner The address from which the balance will be retrieved\n * @return balance of the owner\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the BEP-20 specification\n /// !!!!!!!!!!!!!!\n ///\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n */\n function transfer(address dst, uint256 amount) external;\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the BEP-20 specification\n /// !!!!!!!!!!!!!!\n ///\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n */\n function transferFrom(address src, address dst, uint256 amount) external;\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved\n * @return success Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external returns (bool success);\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return remaining The number of tokens allowed to be spent\n */\n function allowance(address owner, address spender) external view returns (uint256 remaining);\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n}\n" + }, + "contracts/Tokens/Prime/IPrime.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.5.16;\n\n/**\n * @title IPrime\n * @author Venus\n * @notice Interface for Prime Token\n */\ninterface IPrime {\n /**\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\n * @param user the account address whose balance was updated\n */\n function xvsUpdated(address user) external;\n\n /**\n * @notice accrues interest and updates score for an user for a specific market\n * @param user the account address for which to accrue interest and update score\n * @param market the market for which to accrue interest and update score\n */\n function accrueInterestAndUpdateScore(address user, address market) external;\n\n /**\n * @notice Distributes income from market since last distribution\n * @param vToken the market for which to distribute the income\n */\n function accrueInterest(address vToken) external;\n}\n" + }, + "contracts/Tokens/VAI/lib.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n\npragma solidity ^0.5.16;\n\ncontract LibNote {\n event LogNote(\n bytes4 indexed sig,\n address indexed usr,\n bytes32 indexed arg1,\n bytes32 indexed arg2,\n bytes data\n ) anonymous;\n\n modifier note() {\n _;\n assembly {\n // log an 'anonymous' event with a constant 6 words of calldata\n // and four indexed topics: selector, caller, arg1 and arg2\n let mark := msize() // end of memory ensures zero\n mstore(0x40, add(mark, 288)) // update free memory pointer\n mstore(mark, 0x20) // bytes type data offset\n mstore(add(mark, 0x20), 224) // bytes size (padded)\n calldatacopy(add(mark, 0x40), 0, 224) // bytes payload\n log4(\n mark,\n 288, // calldata\n shl(224, shr(224, calldataload(0))), // msg.sig\n caller(), // msg.sender\n calldataload(4), // arg1\n calldataload(36) // arg2\n )\n }\n }\n}\n" + }, + "contracts/Tokens/VAI/VAI.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\n\n// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see .\n\npragma solidity ^0.5.16;\n\nimport \"./lib.sol\";\n\ncontract VAI is LibNote {\n // --- Auth ---\n mapping(address => uint) public wards;\n\n function rely(address guy) external note auth {\n wards[guy] = 1;\n }\n\n function deny(address guy) external note auth {\n wards[guy] = 0;\n }\n\n modifier auth() {\n require(wards[msg.sender] == 1, \"VAI/not-authorized\");\n _;\n }\n\n // --- BEP20 Data ---\n string public constant name = \"VAI Stablecoin\";\n string public constant symbol = \"VAI\";\n string public constant version = \"1\";\n uint8 public constant decimals = 18;\n uint256 public totalSupply;\n\n mapping(address => uint) public balanceOf;\n mapping(address => mapping(address => uint)) public allowance;\n mapping(address => uint) public nonces;\n\n event Approval(address indexed src, address indexed guy, uint wad);\n event Transfer(address indexed src, address indexed dst, uint wad);\n\n // --- Math ---\n function add(uint x, uint y) internal pure returns (uint z) {\n require((z = x + y) >= x, \"VAI math error\");\n }\n\n function sub(uint x, uint y) internal pure returns (uint z) {\n require((z = x - y) <= x, \"VAI math error\");\n }\n\n // --- EIP712 niceties ---\n bytes32 public DOMAIN_SEPARATOR;\n // bytes32 public constant PERMIT_TYPEHASH = keccak256(\"Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)\");\n bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb;\n\n constructor(uint256 chainId_) public {\n wards[msg.sender] = 1;\n DOMAIN_SEPARATOR = keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(name)),\n keccak256(bytes(version)),\n chainId_,\n address(this)\n )\n );\n }\n\n // --- Token ---\n function transfer(address dst, uint wad) external returns (bool) {\n return transferFrom(msg.sender, dst, wad);\n }\n\n function transferFrom(address src, address dst, uint wad) public returns (bool) {\n require(balanceOf[src] >= wad, \"VAI/insufficient-balance\");\n if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {\n require(allowance[src][msg.sender] >= wad, \"VAI/insufficient-allowance\");\n allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad);\n }\n balanceOf[src] = sub(balanceOf[src], wad);\n balanceOf[dst] = add(balanceOf[dst], wad);\n emit Transfer(src, dst, wad);\n return true;\n }\n\n function mint(address usr, uint wad) external auth {\n balanceOf[usr] = add(balanceOf[usr], wad);\n totalSupply = add(totalSupply, wad);\n emit Transfer(address(0), usr, wad);\n }\n\n function burn(address usr, uint wad) external {\n require(balanceOf[usr] >= wad, \"VAI/insufficient-balance\");\n if (usr != msg.sender && allowance[usr][msg.sender] != uint(-1)) {\n require(allowance[usr][msg.sender] >= wad, \"VAI/insufficient-allowance\");\n allowance[usr][msg.sender] = sub(allowance[usr][msg.sender], wad);\n }\n balanceOf[usr] = sub(balanceOf[usr], wad);\n totalSupply = sub(totalSupply, wad);\n emit Transfer(usr, address(0), wad);\n }\n\n function approve(address usr, uint wad) external returns (bool) {\n allowance[msg.sender][usr] = wad;\n emit Approval(msg.sender, usr, wad);\n return true;\n }\n\n // --- Alias ---\n function push(address usr, uint wad) external {\n transferFrom(msg.sender, usr, wad);\n }\n\n function pull(address usr, uint wad) external {\n transferFrom(usr, msg.sender, wad);\n }\n\n function move(address src, address dst, uint wad) external {\n transferFrom(src, dst, wad);\n }\n\n // --- Approve by signature ---\n function permit(\n address holder,\n address spender,\n uint256 nonce,\n uint256 expiry,\n bool allowed,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR,\n keccak256(abi.encode(PERMIT_TYPEHASH, holder, spender, nonce, expiry, allowed))\n )\n );\n\n require(holder != address(0), \"VAI/invalid-address-0\");\n require(holder == ecrecover(digest, v, r, s), \"VAI/invalid-permit\");\n require(expiry == 0 || now <= expiry, \"VAI/permit-expired\");\n require(nonce == nonces[holder]++, \"VAI/invalid-nonce\");\n uint wad = allowed ? uint(-1) : 0;\n allowance[holder][spender] = wad;\n emit Approval(holder, spender, wad);\n }\n}\n" + }, + "contracts/Tokens/VAI/VAIController.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Oracle/PriceOracle.sol\";\nimport \"../../Utils/ErrorReporter.sol\";\nimport \"../../Utils/Exponential.sol\";\nimport \"../../Comptroller/ComptrollerInterface.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV5.sol\";\nimport \"../VTokens/VToken.sol\";\nimport \"./VAIUnitroller.sol\";\nimport \"./VAI.sol\";\n\n/**\n * @title VAI Comptroller\n * @author Venus\n * @notice This is the implementation contract for the VAIUnitroller proxy\n */\ncontract VAIController is VAIControllerStorageG2, VAIControllerErrorReporter, Exponential {\n /// @notice Initial index used in interest computations\n uint public constant INITIAL_VAI_MINT_INDEX = 1e18;\n\n /// @notice Emitted when Comptroller is changed\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\n\n /// @notice Event emitted when VAI is minted\n event MintVAI(address minter, uint mintVAIAmount);\n\n /// @notice Event emitted when VAI is repaid\n event RepayVAI(address payer, address borrower, uint repayVAIAmount);\n\n /// @notice Event emitted when a borrow is liquidated\n event LiquidateVAI(\n address liquidator,\n address borrower,\n uint repayAmount,\n address vTokenCollateral,\n uint seizeTokens\n );\n\n /// @notice Emitted when treasury guardian is changed\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\n\n /// @notice Emitted when treasury address is changed\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\n\n /// @notice Emitted when treasury percent is changed\n event NewTreasuryPercent(uint oldTreasuryPercent, uint newTreasuryPercent);\n\n /// @notice Event emitted when VAIs are minted and fee are transferred\n event MintFee(address minter, uint feeAmount);\n\n /// @notice Emiitted when VAI base rate is changed\n event NewVAIBaseRate(uint256 oldBaseRateMantissa, uint256 newBaseRateMantissa);\n\n /// @notice Emiitted when VAI float rate is changed\n event NewVAIFloatRate(uint oldFloatRateMantissa, uint newFlatRateMantissa);\n\n /// @notice Emiitted when VAI receiver address is changed\n event NewVAIReceiver(address oldReceiver, address newReceiver);\n\n /// @notice Emiitted when VAI mint cap is changed\n event NewVAIMintCap(uint oldMintCap, uint newMintCap);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\n\n /*** Main Actions ***/\n struct MintLocalVars {\n uint oErr;\n MathError mathErr;\n uint mintAmount;\n uint accountMintVAINew;\n uint accountMintableVAI;\n }\n\n function initialize() external onlyAdmin {\n require(vaiMintIndex == 0, \"already initialized\");\n\n vaiMintIndex = INITIAL_VAI_MINT_INDEX;\n accrualBlockNumber = getBlockNumber();\n mintCap = uint256(-1);\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n }\n\n function _become(VAIUnitroller unitroller) external {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can change brains\");\n require(unitroller._acceptImplementation() == 0, \"change not authorized\");\n }\n\n /**\n * @notice The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance.\n * The amount minted must be less than the user's Account Liquidity and the mint vai limit.\n * @param mintVAIAmount The amount of the VAI to be minted.\n * @return 0 on success, otherwise an error code\n */\n // solhint-disable-next-line code-complexity\n function mintVAI(uint mintVAIAmount) external nonReentrant returns (uint) {\n if (address(comptroller) != address(0)) {\n require(mintVAIAmount > 0, \"mintVAIAmount cannot be zero\");\n require(!comptroller.protocolPaused(), \"protocol is paused\");\n\n accrueVAIInterest();\n\n MintLocalVars memory vars;\n\n address minter = msg.sender;\n uint vaiTotalSupply = EIP20Interface(getVAIAddress()).totalSupply();\n uint vaiNewTotalSupply;\n\n (vars.mathErr, vaiNewTotalSupply) = addUInt(vaiTotalSupply, mintVAIAmount);\n require(vaiNewTotalSupply <= mintCap, \"mint cap reached\");\n\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_FEE_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n (vars.oErr, vars.accountMintableVAI) = getMintableVAI(minter);\n if (vars.oErr != uint(Error.NO_ERROR)) {\n return uint(Error.REJECTION);\n }\n\n // check that user have sufficient mintableVAI balance\n if (mintVAIAmount > vars.accountMintableVAI) {\n return fail(Error.REJECTION, FailureInfo.VAI_MINT_REJECTION);\n }\n\n // Calculate the minted balance based on interest index\n uint totalMintedVAI = comptroller.mintedVAIs(minter);\n\n if (totalMintedVAI > 0) {\n uint256 repayAmount = getVAIRepayAmount(minter);\n uint remainedAmount;\n\n (vars.mathErr, remainedAmount) = subUInt(repayAmount, totalMintedVAI);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_FEE_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n (vars.mathErr, pastVAIInterest[minter]) = addUInt(pastVAIInterest[minter], remainedAmount);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_FEE_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n totalMintedVAI = repayAmount;\n }\n\n (vars.mathErr, vars.accountMintVAINew) = addUInt(totalMintedVAI, mintVAIAmount);\n require(vars.mathErr == MathError.NO_ERROR, \"VAI_MINT_AMOUNT_CALCULATION_FAILED\");\n uint error = comptroller.setMintedVAIOf(minter, vars.accountMintVAINew);\n if (error != 0) {\n return error;\n }\n\n uint feeAmount;\n uint remainedAmount;\n vars.mintAmount = mintVAIAmount;\n if (treasuryPercent != 0) {\n (vars.mathErr, feeAmount) = mulUInt(vars.mintAmount, treasuryPercent);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_FEE_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n (vars.mathErr, feeAmount) = divUInt(feeAmount, 1e18);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_FEE_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n (vars.mathErr, remainedAmount) = subUInt(vars.mintAmount, feeAmount);\n if (vars.mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.MINT_FEE_CALCULATION_FAILED, uint(vars.mathErr));\n }\n\n VAI(getVAIAddress()).mint(treasuryAddress, feeAmount);\n\n emit MintFee(minter, feeAmount);\n } else {\n remainedAmount = vars.mintAmount;\n }\n\n VAI(getVAIAddress()).mint(minter, remainedAmount);\n vaiMinterInterestIndex[minter] = vaiMintIndex;\n\n emit MintVAI(minter, remainedAmount);\n\n return uint(Error.NO_ERROR);\n }\n }\n\n /**\n * @notice The repay function transfers VAI into the protocol and burn, reducing the user's borrow balance.\n * Before repaying an asset, users must first approve the VAI to access their VAI balance.\n * @param repayVAIAmount The amount of the VAI to be repaid.\n * @return 0 on success, otherwise an error code\n */\n function repayVAI(uint repayVAIAmount) external nonReentrant returns (uint, uint) {\n if (address(comptroller) != address(0)) {\n accrueVAIInterest();\n\n require(repayVAIAmount > 0, \"repayVAIAmount cannt be zero\");\n\n require(!comptroller.protocolPaused(), \"protocol is paused\");\n\n return repayVAIFresh(msg.sender, msg.sender, repayVAIAmount);\n }\n }\n\n /**\n * @notice Repay VAI Internal\n * @notice Borrowed VAIs are repaid by another user (possibly the borrower).\n * @param payer the account paying off the VAI\n * @param borrower the account with the debt being payed off\n * @param repayAmount the amount of VAI being returned\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayVAIFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\n MathError mErr;\n\n (uint burn, uint partOfCurrentInterest, uint partOfPastInterest) = getVAICalculateRepayAmount(\n borrower,\n repayAmount\n );\n\n VAI(getVAIAddress()).burn(payer, burn);\n bool success = VAI(getVAIAddress()).transferFrom(payer, receiver, partOfCurrentInterest);\n require(success == true, \"failed to transfer VAI fee\");\n\n uint vaiBalanceBorrower = comptroller.mintedVAIs(borrower);\n uint accountVAINew;\n\n (mErr, accountVAINew) = subUInt(vaiBalanceBorrower, burn);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, accountVAINew) = subUInt(accountVAINew, partOfPastInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, pastVAIInterest[borrower]) = subUInt(pastVAIInterest[borrower], partOfPastInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n uint error = comptroller.setMintedVAIOf(borrower, accountVAINew);\n if (error != 0) {\n return (error, 0);\n }\n emit RepayVAI(payer, borrower, burn);\n\n return (uint(Error.NO_ERROR), burn);\n }\n\n /**\n * @notice The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of vai to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function liquidateVAI(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external nonReentrant returns (uint, uint) {\n require(!comptroller.protocolPaused(), \"protocol is paused\");\n\n uint error = vTokenCollateral.accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\n }\n\n // liquidateVAIFresh emits borrow-specific logs on errors, so we don't need to\n return liquidateVAIFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral by repay borrowers VAI.\n * The collateral seized is transferred to the liquidator.\n * @param liquidator The address repaying the VAI and seizing collateral\n * @param borrower The borrower of this VAI to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the VAI to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment VAI.\n */\n function liquidateVAIFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) internal returns (uint, uint) {\n if (address(comptroller) != address(0)) {\n accrueVAIInterest();\n\n /* Fail if liquidate not allowed */\n uint allowed = comptroller.liquidateBorrowAllowed(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n repayAmount\n );\n if (allowed != 0) {\n return (failOpaque(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n //if (vTokenCollateral.accrualBlockNumber() != accrualBlockNumber) {\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\n }\n\n /* Fail if repayAmount = -1 */\n if (repayAmount == uint(-1)) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n /* Fail if repayVAI fails */\n (uint repayBorrowError, uint actualRepayAmount) = repayVAIFresh(liquidator, borrower, repayAmount);\n if (repayBorrowError != uint(Error.NO_ERROR)) {\n return (fail(Error(repayBorrowError), FailureInfo.VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateVAICalculateSeizeTokens(\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(\n amountSeizeError == uint(Error.NO_ERROR),\n \"VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\"\n );\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"VAI_LIQUIDATE_SEIZE_TOO_MUCH\");\n\n uint seizeError;\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\n require(seizeError == uint(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateVAI(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n\n /* We call the defense hook */\n comptroller.liquidateBorrowVerify(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n actualRepayAmount,\n seizeTokens\n );\n\n return (uint(Error.NO_ERROR), actualRepayAmount);\n }\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Sets a new comptroller\n * @dev Admin function to set a new comptroller\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptroller(ComptrollerInterface comptroller_) external returns (uint) {\n // Check caller is admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\n }\n\n ComptrollerInterface oldComptroller = comptroller;\n comptroller = comptroller_;\n emit NewComptroller(oldComptroller, comptroller_);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account total supply balance.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountAmountLocalVars {\n uint oErr;\n MathError mErr;\n uint sumSupply;\n uint marketSupply;\n uint sumBorrowPlusEffects;\n uint vTokenBalance;\n uint borrowBalance;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp exchangeRate;\n Exp oraclePrice;\n Exp tokensToDenom;\n }\n\n // solhint-disable-next-line code-complexity\n function getMintableVAI(address minter) public view returns (uint, uint) {\n PriceOracle oracle = comptroller.oracle();\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\n\n AccountAmountLocalVars memory vars; // Holds all our calculation results\n\n uint accountMintableVAI;\n uint i;\n\n /**\n * We use this formula to calculate mintable VAI amount.\n * totalSupplyAmount * VAIMintRate - (totalBorrowAmount + mintedVAIOf)\n */\n for (i = 0; i < enteredMarkets.length; i++) {\n (vars.oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = enteredMarkets[i]\n .getAccountSnapshot(minter);\n if (vars.oErr != 0) {\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\n return (uint(Error.SNAPSHOT_ERROR), 0);\n }\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n // Get the normalized price of the asset\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(enteredMarkets[i]);\n if (vars.oraclePriceMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\n\n (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.oraclePrice);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n\n // marketSupply = tokensToDenom * vTokenBalance\n (vars.mErr, vars.marketSupply) = mulScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n\n (, uint collateralFactorMantissa) = comptroller.markets(address(enteredMarkets[i]));\n (vars.mErr, vars.marketSupply) = mulUInt(vars.marketSupply, collateralFactorMantissa);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, vars.marketSupply) = divUInt(vars.marketSupply, 1e18);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, vars.sumSupply) = addUInt(vars.sumSupply, vars.marketSupply);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\n (vars.mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(\n vars.oraclePrice,\n vars.borrowBalance,\n vars.sumBorrowPlusEffects\n );\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n }\n\n uint totalMintedVAI = comptroller.mintedVAIs(minter);\n uint256 repayAmount = 0;\n\n if (totalMintedVAI > 0) {\n repayAmount = getVAIRepayAmount(minter);\n }\n\n (vars.mErr, vars.sumBorrowPlusEffects) = addUInt(vars.sumBorrowPlusEffects, repayAmount);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, accountMintableVAI) = mulUInt(vars.sumSupply, comptroller.vaiMintRate());\n require(vars.mErr == MathError.NO_ERROR, \"VAI_MINT_AMOUNT_CALCULATION_FAILED\");\n\n (vars.mErr, accountMintableVAI) = divUInt(accountMintableVAI, 10000);\n require(vars.mErr == MathError.NO_ERROR, \"VAI_MINT_AMOUNT_CALCULATION_FAILED\");\n\n (vars.mErr, accountMintableVAI) = subUInt(accountMintableVAI, vars.sumBorrowPlusEffects);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint(Error.REJECTION), 0);\n }\n\n return (uint(Error.NO_ERROR), accountMintableVAI);\n }\n\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint newTreasuryPercent\n ) external returns (uint) {\n // Check caller is admin\n if (!(msg.sender == admin || msg.sender == treasuryGuardian)) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_TREASURY_OWNER_CHECK);\n }\n\n require(newTreasuryPercent < 1e18, \"treasury percent cap overflow\");\n\n address oldTreasuryGuardian = treasuryGuardian;\n address oldTreasuryAddress = treasuryAddress;\n uint oldTreasuryPercent = treasuryPercent;\n\n treasuryGuardian = newTreasuryGuardian;\n treasuryAddress = newTreasuryAddress;\n treasuryPercent = newTreasuryPercent;\n\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\n\n return uint(Error.NO_ERROR);\n }\n\n function getVAIRepayRate() public view returns (uint) {\n PriceOracle oracle = comptroller.oracle();\n MathError mErr;\n\n if (baseRateMantissa > 0) {\n if (floatRateMantissa > 0) {\n uint oraclePrice = oracle.getUnderlyingPrice(VToken(getVAIAddress()));\n if (1e18 > oraclePrice) {\n uint delta;\n uint rate;\n\n (mErr, delta) = subUInt(1e18, oraclePrice);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, delta) = mulUInt(delta, floatRateMantissa);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, delta) = divUInt(delta, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, rate) = addUInt(delta, baseRateMantissa);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n return rate;\n } else {\n return baseRateMantissa;\n }\n } else {\n return baseRateMantissa;\n }\n } else {\n return 0;\n }\n }\n\n function getVAIRepayRatePerBlock() public view returns (uint) {\n uint yearlyRate = getVAIRepayRate();\n\n MathError mErr;\n uint rate;\n\n (mErr, rate) = divUInt(yearlyRate, getBlocksPerYear());\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n return rate;\n }\n\n function getVAIMinterInterestIndex(address minter) public view returns (uint) {\n uint storedIndex = vaiMinterInterestIndex[minter];\n // If the user minted VAI before the stability fee was introduced, accrue\n // starting from stability fee launch\n if (storedIndex == 0) {\n return INITIAL_VAI_MINT_INDEX;\n }\n return storedIndex;\n }\n\n /**\n * @notice Get the current total VAI a user needs to repay\n * @param account The address of the VAI borrower\n * @return (uint) The total amount of VAI the user needs to repay\n */\n function getVAIRepayAmount(address account) public view returns (uint) {\n MathError mErr;\n uint delta;\n\n uint amount = comptroller.mintedVAIs(account);\n uint interest = pastVAIInterest[account];\n uint totalMintedVAI;\n uint newInterest;\n\n (mErr, totalMintedVAI) = subUInt(amount, interest);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, delta) = subUInt(vaiMintIndex, getVAIMinterInterestIndex(account));\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, newInterest) = mulUInt(delta, totalMintedVAI);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, newInterest) = divUInt(newInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, amount) = addUInt(amount, newInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n return amount;\n }\n\n /**\n * @notice Calculate how much VAI the user needs to repay\n * @param borrower The address of the VAI borrower\n * @param repayAmount The amount of VAI being returned\n * @return (uint, uint, uint) Amount of VAI to be burned, amount of VAI the user needs to pay in current interest and amount of VAI the user needs to pay in past interest\n */\n function getVAICalculateRepayAmount(address borrower, uint256 repayAmount) public view returns (uint, uint, uint) {\n MathError mErr;\n uint256 totalRepayAmount = getVAIRepayAmount(borrower);\n uint currentInterest;\n\n (mErr, currentInterest) = subUInt(totalRepayAmount, comptroller.mintedVAIs(borrower));\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, currentInterest) = addUInt(pastVAIInterest[borrower], currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n uint burn;\n uint partOfCurrentInterest = currentInterest;\n uint partOfPastInterest = pastVAIInterest[borrower];\n\n if (repayAmount >= totalRepayAmount) {\n (mErr, burn) = subUInt(totalRepayAmount, currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n } else {\n uint delta;\n\n (mErr, delta) = mulUInt(repayAmount, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_PART_CALCULATION_FAILED\");\n\n (mErr, delta) = divUInt(delta, totalRepayAmount);\n require(mErr == MathError.NO_ERROR, \"VAI_PART_CALCULATION_FAILED\");\n\n uint totalMintedAmount;\n (mErr, totalMintedAmount) = subUInt(totalRepayAmount, currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_MINTED_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, burn) = mulUInt(totalMintedAmount, delta);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, burn) = divUInt(burn, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfCurrentInterest) = mulUInt(currentInterest, delta);\n require(mErr == MathError.NO_ERROR, \"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfCurrentInterest) = divUInt(partOfCurrentInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfPastInterest) = mulUInt(pastVAIInterest[borrower], delta);\n require(mErr == MathError.NO_ERROR, \"VAI_PAST_INTEREST_CALCULATION_FAILED\");\n\n (mErr, partOfPastInterest) = divUInt(partOfPastInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_PAST_INTEREST_CALCULATION_FAILED\");\n }\n\n return (burn, partOfCurrentInterest, partOfPastInterest);\n }\n\n function accrueVAIInterest() public {\n MathError mErr;\n uint delta;\n\n (mErr, delta) = mulUInt(getVAIRepayRatePerBlock(), getBlockNumber() - accrualBlockNumber);\n require(mErr == MathError.NO_ERROR, \"VAI_INTEREST_ACCURE_FAILED\");\n\n (mErr, delta) = addUInt(delta, vaiMintIndex);\n require(mErr == MathError.NO_ERROR, \"VAI_INTEREST_ACCURE_FAILED\");\n\n vaiMintIndex = delta;\n accrualBlockNumber = getBlockNumber();\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlAddress New address for the access control\n */\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\n _ensureNonzeroAddress(newAccessControlAddress);\n\n address oldAccessControlAddress = accessControl;\n accessControl = newAccessControlAddress;\n emit NewAccessControl(oldAccessControlAddress, accessControl);\n }\n\n /**\n * @notice Set VAI borrow base rate\n * @param newBaseRateMantissa the base rate multiplied by 10**18\n */\n function setBaseRate(uint newBaseRateMantissa) external {\n _ensureAllowed(\"setBaseRate(uint256)\");\n\n uint old = baseRateMantissa;\n baseRateMantissa = newBaseRateMantissa;\n emit NewVAIBaseRate(old, baseRateMantissa);\n }\n\n /**\n * @notice Set VAI borrow float rate\n * @param newFloatRateMantissa the VAI float rate multiplied by 10**18\n */\n function setFloatRate(uint newFloatRateMantissa) external {\n _ensureAllowed(\"setFloatRate(uint256)\");\n\n uint old = floatRateMantissa;\n floatRateMantissa = newFloatRateMantissa;\n emit NewVAIFloatRate(old, floatRateMantissa);\n }\n\n /**\n * @notice Set VAI stability fee receiver address\n * @param newReceiver the address of the VAI fee receiver\n */\n function setReceiver(address newReceiver) external onlyAdmin {\n require(newReceiver != address(0), \"invalid receiver address\");\n\n address old = receiver;\n receiver = newReceiver;\n emit NewVAIReceiver(old, newReceiver);\n }\n\n /**\n * @notice Set VAI mint cap\n * @param _mintCap the amount of VAI that can be minted\n */\n function setMintCap(uint _mintCap) external {\n _ensureAllowed(\"setMintCap(uint256)\");\n\n uint old = mintCap;\n mintCap = _mintCap;\n emit NewVAIMintCap(old, _mintCap);\n }\n\n function getBlockNumber() internal view returns (uint) {\n return block.number;\n }\n\n function getBlocksPerYear() public view returns (uint) {\n return 10512000; //(24 * 60 * 60 * 365) / 3;\n }\n\n /**\n * @notice Return the address of the VAI token\n * @return The address of VAI\n */\n function getVAIAddress() public view returns (address) {\n return 0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7;\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin can\");\n _;\n }\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n function _ensureAllowed(string memory functionSig) private view {\n require(IAccessControlManagerV5(accessControl).isAllowedToCall(msg.sender, functionSig), \"access denied\");\n }\n\n /// @notice Reverts if the passed address is zero\n function _ensureNonzeroAddress(address someone) private pure {\n require(someone != address(0), \"can't be zero address\");\n }\n}\n" + }, + "contracts/Tokens/VAI/VAIControllerInterface.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../VTokens/VTokenInterfaces.sol\";\n\ncontract VAIControllerInterface {\n function getVAIAddress() public view returns (address);\n\n function getMintableVAI(address minter) public view returns (uint, uint);\n\n function mintVAI(address minter, uint mintVAIAmount) external returns (uint);\n\n function repayVAI(address repayer, uint repayVAIAmount) external returns (uint);\n\n function liquidateVAI(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint, uint);\n\n function _initializeVenusVAIState(uint blockNumber) external returns (uint);\n\n function updateVenusVAIMintIndex() external returns (uint);\n\n function calcDistributeVAIMinterVenus(address vaiMinter) external returns (uint, uint, uint, uint);\n\n function getVAIRepayAmount(address account) public view returns (uint);\n}\n" + }, + "contracts/Tokens/VAI/VAIControllerStorage.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Comptroller/ComptrollerInterface.sol\";\n\ncontract VAIUnitrollerAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of Unitroller\n */\n address public vaiControllerImplementation;\n\n /**\n * @notice Pending brains of Unitroller\n */\n address public pendingVAIControllerImplementation;\n}\n\ncontract VAIControllerStorageG1 is VAIUnitrollerAdminStorage {\n ComptrollerInterface public comptroller;\n\n struct VenusVAIState {\n /// @notice The last updated venusVAIMintIndex\n uint224 index;\n /// @notice The block number the index was last updated at\n uint32 block;\n }\n\n /// @notice The Venus VAI state\n VenusVAIState public venusVAIState;\n\n /// @notice The Venus VAI state initialized\n bool public isVenusVAIInitialized;\n\n /// @notice The Venus VAI minter index as of the last time they accrued XVS\n mapping(address => uint) public venusVAIMinterIndex;\n}\n\ncontract VAIControllerStorageG2 is VAIControllerStorageG1 {\n /// @notice Treasury Guardian address\n address public treasuryGuardian;\n\n /// @notice Treasury address\n address public treasuryAddress;\n\n /// @notice Fee percent of accrued interest with decimal 18\n uint256 public treasuryPercent;\n\n /// @notice Guard variable for re-entrancy checks\n bool internal _notEntered;\n\n /// @notice The base rate for stability fee\n uint public baseRateMantissa;\n\n /// @notice The float rate for stability fee\n uint public floatRateMantissa;\n\n /// @notice The address for VAI interest receiver\n address public receiver;\n\n /// @notice Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\n uint public vaiMintIndex;\n\n /// @notice Block number that interest was last accrued at\n uint internal accrualBlockNumber;\n\n /// @notice Global vaiMintIndex as of the most recent balance-changing action for user\n mapping(address => uint) internal vaiMinterInterestIndex;\n\n /// @notice Tracks the amount of mintedVAI of a user that represents the accrued interest\n mapping(address => uint) public pastVAIInterest;\n\n /// @notice VAI mint cap\n uint public mintCap;\n\n /// @notice Access control manager address\n address public accessControl;\n}\n" + }, + "contracts/Tokens/VAI/VAIUnitroller.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Utils/ErrorReporter.sol\";\nimport \"./VAIControllerStorage.sol\";\n\n/**\n * @title VAI Unitroller\n * @author Venus\n * @notice This is the proxy contract for the VAIComptroller\n */\ncontract VAIUnitroller is VAIUnitrollerAdminStorage, VAIControllerErrorReporter {\n /**\n * @notice Emitted when pendingVAIControllerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingVAIControllerImplementation is accepted, which means comptroller implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor() public {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation = pendingVAIControllerImplementation;\n\n pendingVAIControllerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public returns (uint) {\n // Check caller is pendingImplementation\n if (msg.sender != pendingVAIControllerImplementation) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldImplementation = vaiControllerImplementation;\n address oldPendingImplementation = pendingVAIControllerImplementation;\n\n vaiControllerImplementation = pendingVAIControllerImplementation;\n\n pendingVAIControllerImplementation = address(0);\n\n emit NewImplementation(oldImplementation, vaiControllerImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\n // Check caller = admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n }\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n function() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = vaiControllerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/Tokens/VRT/VRT.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Utils/Tokenlock.sol\";\n\ncontract VRT is Tokenlock {\n /// @notice BEP-20 token name for this token\n string public constant name = \"Venus Reward Token\";\n\n /// @notice BEP-20 token symbol for this token\n string public constant symbol = \"VRT\";\n\n /// @notice BEP-20 token decimals for this token\n uint8 public constant decimals = 18;\n\n /// @notice Total number of tokens in circulation\n uint public constant totalSupply = 30000000000e18; // 30 billion VRT\n\n /// @notice Allowance amounts on behalf of others\n mapping(address => mapping(address => uint96)) internal allowances;\n\n /// @notice Official record of token balances for each account\n mapping(address => uint96) internal balances;\n\n /// @notice A record of each accounts delegate\n mapping(address => address) public delegates;\n\n /// @notice A checkpoint for marking number of votes from a given block\n struct Checkpoint {\n uint32 fromBlock;\n uint96 votes;\n }\n\n /// @notice A record of votes checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH =\n keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /// @notice An event thats emitted when an account changes its delegate\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /// @notice An event thats emitted when a delegate account's vote balance changes\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\n\n /// @notice The standard BEP-20 transfer event\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @notice The standard BEP-20 approval event\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Construct a new VRT token\n * @param account The initial account to grant all the tokens\n */\n constructor(address account) public {\n balances[account] = uint96(totalSupply);\n emit Transfer(address(0), account, totalSupply);\n }\n\n /**\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\n * @param account The address of the account holding the funds\n * @param spender The address of the account spending the funds\n * @return The number of tokens approved\n */\n function allowance(address account, address spender) external view returns (uint) {\n return allowances[account][spender];\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint rawAmount) external validLock returns (bool) {\n uint96 amount;\n if (rawAmount == uint(-1)) {\n amount = uint96(-1);\n } else {\n amount = safe96(rawAmount, \"VRT::approve: amount exceeds 96 bits\");\n }\n\n allowances[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n /**\n * @notice Get the number of tokens held by the `account`\n * @param account The address of the account to get the balance of\n * @return The number of tokens held\n */\n function balanceOf(address account) external view returns (uint) {\n return balances[account];\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint rawAmount) external validLock returns (bool) {\n uint96 amount = safe96(rawAmount, \"VRT::transfer: amount exceeds 96 bits\");\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint rawAmount) external validLock returns (bool) {\n address spender = msg.sender;\n uint96 spenderAllowance = allowances[src][spender];\n uint96 amount = safe96(rawAmount, \"VRT::approve: amount exceeds 96 bits\");\n\n if (spender != src && spenderAllowance != uint96(-1)) {\n uint96 newAllowance = sub96(\n spenderAllowance,\n amount,\n \"VRT::transferFrom: transfer amount exceeds spender allowance\"\n );\n allowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public validLock {\n return _delegate(msg.sender, delegatee);\n }\n\n /**\n * @notice Delegates votes from signatory to `delegatee`\n * @param delegatee The address to delegate votes to\n * @param nonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v The recovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public validLock {\n bytes32 domainSeparator = keccak256(\n abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this))\n );\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n address signatory = ecrecover(digest, v, r, s);\n require(signatory != address(0), \"VRT::delegateBySig: invalid signature\");\n require(nonce == nonces[signatory]++, \"VRT::delegateBySig: invalid nonce\");\n require(now <= expiry, \"VRT::delegateBySig: signature expired\");\n return _delegate(signatory, delegatee);\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getCurrentVotes(address account) external view returns (uint96) {\n uint32 nCheckpoints = numCheckpoints[account];\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n }\n\n /**\n * @notice Determine the prior number of votes for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param blockNumber The block number to get the vote balance at\n * @return The number of votes the account had as of the given block\n */\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\n require(blockNumber < block.number, \"VRT::getPriorVotes: not yet determined\");\n\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\n return checkpoints[account][nCheckpoints - 1].votes;\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].fromBlock > blockNumber) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.fromBlock == blockNumber) {\n return cp.votes;\n } else if (cp.fromBlock < blockNumber) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return checkpoints[account][lower].votes;\n }\n\n function _delegate(address delegator, address delegatee) internal {\n address currentDelegate = delegates[delegator];\n uint96 delegatorBalance = balances[delegator];\n delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _transferTokens(address src, address dst, uint96 amount) internal {\n require(src != address(0), \"VRT::_transferTokens: cannot transfer from the zero address\");\n require(dst != address(0), \"VRT::_transferTokens: cannot transfer to the zero address\");\n\n balances[src] = sub96(balances[src], amount, \"VRT::_transferTokens: transfer amount exceeds balance\");\n balances[dst] = add96(balances[dst], amount, \"VRT::_transferTokens: transfer amount overflows\");\n emit Transfer(src, dst, amount);\n\n _moveDelegates(delegates[src], delegates[dst], amount);\n }\n\n function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {\n if (srcRep != dstRep && amount > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\n uint96 srcRepNew = sub96(srcRepOld, amount, \"VRT::_moveVotes: vote amount underflows\");\n _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\n uint96 dstRepNew = add96(dstRepOld, amount, \"VRT::_moveVotes: vote amount overflows\");\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n }\n }\n }\n\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\n uint32 blockNumber = safe32(block.number, \"VRT::_writeCheckpoint: block number exceeds 32 bits\");\n\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n } else {\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\n numCheckpoints[delegatee] = nCheckpoints + 1;\n }\n\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n }\n\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n require(n < 2 ** 32, errorMessage);\n return uint32(n);\n }\n\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\n require(n < 2 ** 96, errorMessage);\n return uint96(n);\n }\n\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n uint96 c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function getChainId() internal pure returns (uint) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n return chainId;\n }\n}\n" + }, + "contracts/Tokens/VRT/VRTConverter.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Utils/IBEP20.sol\";\nimport \"../../Utils/SafeBEP20.sol\";\nimport \"../XVS/IXVSVesting.sol\";\nimport \"./VRTConverterStorage.sol\";\nimport \"./VRTConverterProxy.sol\";\n\n/**\n * @title Venus's VRTConversion Contract\n * @author Venus\n */\ncontract VRTConverter is VRTConverterStorage {\n using SafeMath for uint256;\n using SafeBEP20 for IBEP20;\n\n address public constant DEAD_ADDRESS = 0x000000000000000000000000000000000000dEaD;\n\n /// @notice decimal precision for VRT\n uint256 public constant vrtDecimalsMultiplier = 1e18;\n\n /// @notice decimal precision for XVS\n uint256 public constant xvsDecimalsMultiplier = 1e18;\n\n /// @notice Emitted when an admin set conversion info\n event ConversionInfoSet(\n uint256 conversionRatio,\n uint256 conversionStartTime,\n uint256 conversionPeriod,\n uint256 conversionEndTime\n );\n\n /// @notice Emitted when token conversion is done\n event TokenConverted(\n address reedeemer,\n address vrtAddress,\n uint256 vrtAmount,\n address xvsAddress,\n uint256 xvsAmount\n );\n\n /// @notice Emitted when an admin withdraw converted token\n event TokenWithdraw(address token, address to, uint256 amount);\n\n /// @notice Emitted when XVSVestingAddress is set\n event XVSVestingSet(address xvsVestingAddress);\n\n constructor() public {}\n\n function initialize(\n address _vrtAddress,\n address _xvsAddress,\n uint256 _conversionRatio,\n uint256 _conversionStartTime,\n uint256 _conversionPeriod\n ) public {\n require(msg.sender == admin, \"only admin may initialize the VRTConverter\");\n require(initialized == false, \"VRTConverter is already initialized\");\n\n require(_vrtAddress != address(0), \"vrtAddress cannot be Zero\");\n vrt = IBEP20(_vrtAddress);\n\n require(_xvsAddress != address(0), \"xvsAddress cannot be Zero\");\n xvs = IBEP20(_xvsAddress);\n\n require(_conversionRatio > 0, \"conversionRatio cannot be Zero\");\n conversionRatio = _conversionRatio;\n\n require(_conversionStartTime >= block.timestamp, \"conversionStartTime must be time in the future\");\n require(_conversionPeriod > 0, \"_conversionPeriod is invalid\");\n\n conversionStartTime = _conversionStartTime;\n conversionPeriod = _conversionPeriod;\n conversionEndTime = conversionStartTime.add(conversionPeriod);\n emit ConversionInfoSet(conversionRatio, conversionStartTime, conversionPeriod, conversionEndTime);\n\n totalVrtConverted = 0;\n _notEntered = true;\n initialized = true;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n /**\n * @notice sets XVSVestingProxy Address\n * @dev Note: If XVSVestingProxy is not set, then Conversion is not allowed\n * @param _xvsVestingAddress The XVSVestingProxy Address\n */\n function setXVSVesting(address _xvsVestingAddress) public {\n require(msg.sender == admin, \"only admin may initialize the Vault\");\n require(_xvsVestingAddress != address(0), \"xvsVestingAddress cannot be Zero\");\n xvsVesting = IXVSVesting(_xvsVestingAddress);\n emit XVSVestingSet(_xvsVestingAddress);\n }\n\n modifier isInitialized() {\n require(initialized == true, \"VRTConverter is not initialized\");\n _;\n }\n\n function isConversionActive() public view returns (bool) {\n uint256 currentTime = block.timestamp;\n if (currentTime >= conversionStartTime && currentTime <= conversionEndTime) {\n return true;\n }\n return false;\n }\n\n modifier checkForActiveConversionPeriod() {\n uint256 currentTime = block.timestamp;\n require(currentTime >= conversionStartTime, \"Conversion did not start yet\");\n require(currentTime <= conversionEndTime, \"Conversion Period Ended\");\n _;\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin can\");\n _;\n }\n\n modifier nonZeroAddress(address _address) {\n require(_address != address(0), \"Address cannot be Zero\");\n _;\n }\n\n /**\n * @notice Transfer VRT and redeem XVS\n * @dev Note: If there is not enough XVS, we do not perform the conversion.\n * @param vrtAmount The amount of VRT\n */\n function convert(uint256 vrtAmount) external isInitialized checkForActiveConversionPeriod nonReentrant {\n require(\n address(xvsVesting) != address(0) && address(xvsVesting) != DEAD_ADDRESS,\n \"XVS-Vesting Address is not set\"\n );\n require(vrtAmount > 0, \"VRT amount must be non-zero\");\n totalVrtConverted = totalVrtConverted.add(vrtAmount);\n\n uint256 redeemAmount = vrtAmount.mul(conversionRatio).mul(xvsDecimalsMultiplier).div(1e18).div(\n vrtDecimalsMultiplier\n );\n\n emit TokenConverted(msg.sender, address(vrt), vrtAmount, address(xvs), redeemAmount);\n vrt.safeTransferFrom(msg.sender, DEAD_ADDRESS, vrtAmount);\n xvsVesting.deposit(msg.sender, redeemAmount);\n }\n\n /*** Admin Functions ***/\n function _become(VRTConverterProxy vrtConverterProxy) public {\n require(msg.sender == vrtConverterProxy.admin(), \"only proxy admin can change brains\");\n vrtConverterProxy._acceptImplementation();\n }\n}\n" + }, + "contracts/Tokens/VRT/VRTConverterProxy.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./VRTConverterStorage.sol\";\n\ncontract VRTConverterProxy is VRTConverterAdminStorage {\n /**\n * @notice Emitted when pendingImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingImplementation is accepted, which means VRTConverter implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor(\n address implementation_,\n address _vrtAddress,\n address _xvsAddress,\n uint256 _conversionRatio,\n uint256 _conversionStartTime,\n uint256 _conversionPeriod\n ) public nonZeroAddress(implementation_) nonZeroAddress(_vrtAddress) nonZeroAddress(_xvsAddress) {\n // Creator of the contract is admin during initialization\n admin = msg.sender;\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_);\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(\n implementation_,\n abi.encodeWithSignature(\n \"initialize(address,address,uint256,uint256,uint256)\",\n _vrtAddress,\n _xvsAddress,\n _conversionRatio,\n _conversionStartTime,\n _conversionPeriod\n )\n );\n }\n\n modifier nonZeroAddress(address _address) {\n require(_address != address(0), \"Address cannot be Zero\");\n _;\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n */\n function _setImplementation(address implementation_) public {\n require(msg.sender == admin, \"VRTConverterProxy::_setImplementation: admin only\");\n require(implementation_ != address(0), \"VRTConverterProxy::_setImplementation: invalid implementation address\");\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal nonZeroAddress(callee) returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n return returnData;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(\n address newPendingImplementation\n ) public nonZeroAddress(newPendingImplementation) {\n require(msg.sender == admin, \"Only admin can set Pending Implementation\");\n\n address oldPendingImplementation = pendingImplementation;\n\n pendingImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingImplementation);\n }\n\n /**\n * @notice Accepts new implementation of VRTConverter. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @dev return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public {\n // Check caller is pendingImplementation\n require(\n msg.sender == pendingImplementation,\n \"only address marked as pendingImplementation can accept Implementation\"\n );\n\n // Save current values for inclusion in log\n address oldImplementation = implementation;\n address oldPendingImplementation = pendingImplementation;\n\n implementation = pendingImplementation;\n\n pendingImplementation = address(0);\n\n emit NewImplementation(oldImplementation, implementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingImplementation);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @dev return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public nonZeroAddress(newPendingAdmin) {\n // Check caller = admin\n require(msg.sender == admin, \"only admin can set pending admin\");\n require(newPendingAdmin != pendingAdmin, \"New pendingAdmin can not be same as the previous one\");\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @dev return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public {\n // Check caller is pendingAdmin\n require(msg.sender == pendingAdmin, \"only address marked as pendingAdmin can accept as Admin\");\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n function() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/Tokens/VRT/VRTConverterStorage.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Utils/SafeMath.sol\";\nimport \"../../Utils/IBEP20.sol\";\nimport \"../XVS/IXVSVesting.sol\";\n\ncontract VRTConverterAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of VRTConverter\n */\n address public implementation;\n\n /**\n * @notice Pending brains of VRTConverter\n */\n address public pendingImplementation;\n}\n\ncontract VRTConverterStorage is VRTConverterAdminStorage {\n /// @notice Guard variable for re-entrancy checks\n bool public _notEntered;\n\n /// @notice indicator to check if the contract is initialized\n bool public initialized;\n\n /// @notice The VRT TOKEN!\n IBEP20 public vrt;\n\n /// @notice The XVS TOKEN!\n IBEP20 public xvs;\n\n /// @notice XVSVesting Contract reference\n IXVSVesting public xvsVesting;\n\n /// @notice Conversion ratio from VRT to XVS with decimal 18\n uint256 public conversionRatio;\n\n /// @notice total VRT converted to XVS\n uint256 public totalVrtConverted;\n\n /// @notice Conversion Start time in EpochSeconds\n uint256 public conversionStartTime;\n\n /// @notice ConversionPeriod in Seconds\n uint256 public conversionPeriod;\n\n /// @notice Conversion End time in EpochSeconds\n uint256 public conversionEndTime;\n}\n" + }, + "contracts/Tokens/VTokens/VBep20.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./VToken.sol\";\n\n/**\n * @title Venus's VBep20 Contract\n * @notice vTokens which wrap an EIP-20 underlying\n * @author Venus\n */\ncontract VBep20 is VToken, VBep20Interface {\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits Mint event\n function mint(uint mintAmount) external returns (uint) {\n (uint err, ) = mintInternal(mintAmount);\n return err;\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver The account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits MintBehalf event\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n (uint err, ) = mintBehalfInternal(receiver, mintAmount);\n return err;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrow(uint borrowAmount) external returns (uint) {\n address borrower = msg.sender;\n address payable receiver = msg.sender;\n return borrowInternal(borrower, receiver, borrowAmount);\n }\n\n /**\n * @notice Sender borrows assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the borrower using `comptroller.updateDelegate`\n * @param borrower The borrower, on behalf of whom to borrow.\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrowBehalf(address borrower, uint borrowAmount) external returns (uint) {\n require(comptroller.approvedDelegates(borrower, msg.sender), \"not an approved delegate\");\n address payable receiver = msg.sender;\n return borrowInternal(borrower, receiver, borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrow(uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrowing account\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\n return err;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emit LiquidateBorrow event on success\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n (uint err, ) = liquidateBorrowInternal(borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying tokens to add as reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesAdded event\n function _addReserves(uint addAmount) external returns (uint) {\n return _addReservesInternal(addAmount);\n }\n\n /**\n * @notice Initialize the new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n // VToken initialize does the bulk of the work\n super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set underlying and sanity check it\n underlying = underlying_;\n EIP20Interface(underlying).totalSupply();\n }\n\n /*** Safe Token ***/\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\n * This will revert due to insufficient balance or insufficient allowance.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n *\n * Note: This wrapper safely handles non-standard BEP-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferIn(address from, uint amount) internal returns (uint) {\n uint balanceBefore = EIP20Interface(underlying).balanceOf(address(this));\n EIP20NonStandardInterface(underlying).transferFrom(from, address(this), amount);\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard BEP-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a compliant BEP-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant BEP-20, revert.\n revert(0, 0)\n }\n }\n require(success, \"TOKEN_TRANSFER_IN_FAILED\");\n\n // Calculate the amount that was *actually* transferred\n uint balanceAfter = EIP20Interface(underlying).balanceOf(address(this));\n require(balanceAfter >= balanceBefore, \"TOKEN_TRANSFER_IN_OVERFLOW\");\n return balanceAfter - balanceBefore; // underflow already checked above, just subtract\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\n * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to\n * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified\n * it is >= amount, this should not revert in normal conditions.\n *\n * Note: This wrapper safely handles non-standard BEP-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferOut(address payable to, uint amount) internal {\n EIP20NonStandardInterface(underlying).transfer(to, amount);\n\n bool success;\n assembly {\n switch returndatasize()\n case 0 {\n // This is a non-standard BEP-20\n success := not(0) // set success to true\n }\n case 32 {\n // This is a compliant BEP-20\n returndatacopy(0, 0, 32)\n success := mload(0) // Set `success = returndata` of external call\n }\n default {\n // This is an excessively non-compliant BEP-20, revert.\n revert(0, 0)\n }\n }\n require(success, \"TOKEN_TRANSFER_OUT_FAILED\");\n }\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying tokens owned by this contract\n */\n function getCashPrior() internal view returns (uint) {\n return EIP20Interface(underlying).balanceOf(address(this));\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Delegate.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./VBep20.sol\";\n\n/**\n * @title Venus's VBep20Delegate Contract\n * @notice VTokens which wrap an EIP-20 underlying and are delegated to\n * @author Venus\n */\ncontract VBep20Delegate is VBep20, VDelegateInterface {\n /**\n * @notice Construct an empty delegate\n */\n constructor() public {}\n\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) public {\n // Shh -- currently unused\n data;\n\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _becomeImplementation\");\n }\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() public {\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _resignImplementation\");\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Delegator.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20Delegator Contract\n * @notice vTokens which wrap an EIP-20 underlying and delegate to an implementation\n * @author Venus\n */\ncontract VBep20Delegator is VTokenInterface, VBep20Interface, VDelegatorInterface {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData The encoded args for becomeImplementation\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n ) public {\n // Creator of the contract is admin during initialization\n admin = msg.sender;\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(\n implementation_,\n abi.encodeWithSignature(\n \"initialize(address,address,address,uint256,string,string,uint8)\",\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n )\n );\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_, false, becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n */\n function() external payable {\n require(msg.value == 0, \"VBep20Delegator:fallback: cannot send value to fallback\");\n\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function mint(uint mintAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"mint(uint256)\", mintAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"mintBehalf(address,uint256)\", receiver, mintAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying asset\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeem(uint redeemTokens) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"redeem(uint256)\", redeemTokens));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"redeemUnderlying(uint256)\", redeemAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function borrow(uint borrowAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrow(uint256)\", borrowAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function repayBorrow(uint repayAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"repayBorrow(uint256)\", repayAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrower\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"repayBorrowBehalf(address,uint256)\", borrower, repayAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"liquidateBorrow(address,uint256,address)\", borrower, repayAmount, vTokenCollateral)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint amount) external returns (bool) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"transfer(address,uint256)\", dst, amount));\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint256 amount) external returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"transferFrom(address,address,uint256)\", src, dst, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"approve(address,uint256)\", spender, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"balanceOfUnderlying(address)\", owner));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"totalBorrowsCurrent()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrowBalanceCurrent(address)\", account));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"seize(address,address,uint256)\", liquidator, borrower, seizeTokens)\n );\n return abi.decode(data, (uint));\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setPendingAdmin(address)\", newPendingAdmin)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setReserveFactor(uint256)\", newReserveFactorMantissa)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accepts transfer of admin rights. `msg.sender` must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _acceptAdmin() external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_acceptAdmin()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from admin\n * @param addAmount Amount of reserves to add\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _addReserves(uint addAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_addReserves(uint256)\", addAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReserves(uint reduceAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_reduceReserves(uint256)\", reduceAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"getCash()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (-1 means infinite)\n */\n function allowance(address owner, address spender) external view returns (uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"allowance(address,address)\", owner, spender)\n );\n return abi.decode(data, (uint));\n }\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 (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"balanceOf(address)\", owner));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get a snapshot of the account's balances and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"getAccountSnapshot(address)\", account)\n );\n return abi.decode(data, (uint, uint, uint, uint));\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"borrowRatePerBlock()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"supplyRatePerBlock()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n // @custom:access Only callable by admin\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) public {\n require(msg.sender == admin, \"VBep20Delegator::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature(\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"exchangeRateCurrent()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves.\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n function accrueInterest() public returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"accrueInterest()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setComptroller(address)\", newComptroller)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using `_setInterestRateModelFresh`\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel The new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setInterestRateModel(address)\", newInterestRateModel)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Delegates execution to the implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToImplementation(bytes memory data) public returns (bytes memory) {\n return delegateTo(implementation, data);\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n (bool success, bytes memory returnData) = address(this).staticcall(\n abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data)\n );\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n return abi.decode(returnData, (bytes));\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view returns (uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"borrowBalanceStored(address)\", account)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\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() public view returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"exchangeRateStored()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n return returnData;\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Immutable.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./VBep20.sol\";\n\n/**\n * @title Venus's VBep20Immutable Contract\n * @notice VTokens which wrap an EIP-20 underlying and are immutable\n * @author Venus\n */\ncontract VBep20Immutable is VBep20 {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n ) public {\n // Creator of the contract is admin during initialization\n admin = msg.sender;\n\n // Initialize the market\n initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n );\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n}\n" + }, + "contracts/Tokens/VTokens/VToken.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Comptroller/ComptrollerInterface.sol\";\nimport \"../../Utils/ErrorReporter.sol\";\nimport \"../../Utils/Exponential.sol\";\nimport \"../../Tokens/EIP20Interface.sol\";\nimport \"../../Tokens/EIP20NonStandardInterface.sol\";\nimport \"../../InterestRateModels/InterestRateModel.sol\";\nimport \"./VTokenInterfaces.sol\";\nimport { IAccessControlManagerV5 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV5.sol\";\n\n/**\n * @title Venus's vToken Contract\n * @notice Abstract base for vTokens\n * @author Venus\n */\ncontract VToken is VTokenInterface, Exponential, TokenErrorReporter {\n struct MintLocalVars {\n MathError mathErr;\n uint exchangeRateMantissa;\n uint mintTokens;\n uint totalSupplyNew;\n uint accountTokensNew;\n uint actualMintAmount;\n }\n\n struct RedeemLocalVars {\n MathError mathErr;\n uint exchangeRateMantissa;\n uint redeemTokens;\n uint redeemAmount;\n uint totalSupplyNew;\n uint accountTokensNew;\n }\n\n struct BorrowLocalVars {\n MathError mathErr;\n uint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n }\n\n struct RepayBorrowLocalVars {\n Error err;\n MathError mathErr;\n uint repayAmount;\n uint borrowerIndex;\n uint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n uint actualRepayAmount;\n }\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n // @custom:event Emits Transfer event\n function transfer(address dst, uint256 amount) external nonReentrant returns (bool) {\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n // @custom:event Emits Transfer event\n function transferFrom(address src, address dst, uint256 amount) external nonReentrant returns (bool) {\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n // @custom:event Emits Approval event on successful approve\n function approve(address spender, uint256 amount) external returns (bool) {\n transferAllowances[msg.sender][spender] = amount;\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external returns (uint) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\n ensureNoMathError(mErr);\n return balance;\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return totalBorrows;\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return borrowBalanceStored(account);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n function seize(address liquidator, address borrower, uint seizeTokens) external nonReentrant returns (uint) {\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint) {\n // Check caller = admin\n ensureAdmin(msg.sender);\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewAdmin event on successful acceptance\n // @custom:event Emits NewPendingAdmin event with null new pending admin\n function _acceptAdmin() external returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\n * @dev Governor function to accrue interest and set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewReserveFactor event\n function _setReserveFactor(uint newReserveFactorMantissa_) external nonReentrant returns (uint) {\n ensureAllowed(\"_setReserveFactor(uint256)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\n }\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\n return _setReserveFactorFresh(newReserveFactorMantissa_);\n }\n\n /**\n * @notice Sets the address of the access control manager of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlManagerAddress New address for the access control\n * @return uint 0=success, otherwise will revert\n */\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\n // Check caller is admin\n ensureAdmin(msg.sender);\n\n ensureNonZeroAddress(newAccessControlManagerAddress);\n\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\n accessControlManager = newAccessControlManagerAddress;\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\n * @param reduceAmount_ Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesReduced event\n function _reduceReserves(uint reduceAmount_) external nonReentrant returns (uint) {\n ensureAllowed(\"_reduceReserves(uint256)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n\n // If reserves were reduced in accrueInterest\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\n return _reduceReservesFresh(reduceAmount_);\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (-1 means infinite)\n */\n function allowance(address owner, address spender) external view returns (uint256) {\n return transferAllowances[owner][spender];\n }\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 return accountTokens[owner];\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint) {\n uint vTokenBalance = accountTokens[account];\n uint borrowBalance;\n uint exchangeRateMantissa;\n\n MathError mErr;\n\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0, 0);\n }\n\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0, 0);\n }\n\n return (uint(Error.NO_ERROR), vTokenBalance, borrowBalance, exchangeRateMantissa);\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view returns (uint) {\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view returns (uint) {\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view returns (uint) {\n return getCashPrior();\n }\n\n /**\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\n * @param newReduceReservesBlockDelta_ block difference value\n */\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external returns (uint) {\n require(newReduceReservesBlockDelta_ > 0, \"Invalid Input\");\n ensureAllowed(\"setReduceReservesBlockDelta(uint256)\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protcolShareReserve_ The address of protocol share reserve contract\n */\n function setProtocolShareReserve(address payable protcolShareReserve_) external returns (uint) {\n // Check caller is admin\n ensureAdmin(msg.sender);\n ensureNonZeroAddress(protcolShareReserve_);\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\n protocolShareReserve = protcolShareReserve_;\n }\n\n /**\n * @notice Initialize the money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ EIP-20 name of this token\n * @param symbol_ EIP-20 symbol of this token\n * @param decimals_ EIP-20 decimal precision of this token\n */\n function initialize(\n ComptrollerInterface comptroller_,\n InterestRateModel interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n ensureAdmin(msg.sender);\n require(accrualBlockNumber == 0 && borrowIndex == 0, \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa > 0, \"initial exchange rate must be greater than zero.\");\n\n // Set the comptroller\n uint err = _setComptroller(comptroller_);\n require(err == uint(Error.NO_ERROR), \"setting comptroller failed\");\n\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n accrualBlockNumber = block.number;\n borrowIndex = mantissaOne;\n\n // Set the interest rate model (depends on block number / borrow index)\n err = _setInterestRateModelFresh(interestRateModel_);\n require(err == uint(Error.NO_ERROR), \"setting interest rate model failed\");\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return exchangeRateStored();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\n */\n // @custom:event Emits AccrueInterest event\n function accrueInterest() public returns (uint) {\n /* Remember the initial block number */\n uint currentBlockNumber = block.number;\n uint accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return uint(Error.NO_ERROR);\n }\n\n /* Read the previous values out of storage */\n uint cashPrior = getCashPrior();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\n uint borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n require(borrowRateMantissa <= borrowRateMaxMantissa, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n ensureNoMathError(mathErr);\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor;\n uint interestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\n ensureNoMathError(mathErr);\n if (blockDelta >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentBlockNumber;\n _reduceReservesFresh(totalReservesNew);\n }\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewComptroller event\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint) {\n // Check caller is admin\n ensureAdmin(msg.sender);\n\n ComptrollerInterface oldComptroller = comptroller;\n // Ensure invoke comptroller.isComptroller() returns true\n require(newComptroller.isComptroller(), \"marker method returned false\");\n\n // Set market's comptroller to newComptroller\n comptroller = newComptroller;\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(oldComptroller, newComptroller);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Governance function to accrue interest and update the interest rate model\n * @param newInterestRateModel_ The new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModel(InterestRateModel newInterestRateModel_) public returns (uint) {\n ensureAllowed(\"_setInterestRateModel(address)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\n }\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\n return _setInterestRateModelFresh(newInterestRateModel_);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\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() public view returns (uint) {\n (MathError err, uint result) = exchangeRateStoredInternal();\n ensureNoMathError(err);\n return result;\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view returns (uint) {\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\n ensureNoMathError(err);\n return result;\n }\n\n /**\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\n * @dev Called by both `transfer` and `transferFrom` internally\n * @param spender The address of the account performing the transfer\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param tokens The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\n /* Fail if transfer not allowed */\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\n if (allowed != 0) {\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Do not allow self-transfers */\n if (src == dst) {\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n /* Get the allowance, infinite for the account owner */\n uint startingAllowance = 0;\n if (spender == src) {\n startingAllowance = uint(-1);\n } else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under,over}flow */\n MathError mathErr;\n uint allowanceNew;\n uint srvTokensNew;\n uint dstTokensNew;\n\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\n }\n\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n accountTokens[src] = srvTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if necessary) */\n if (startingAllowance != uint(-1)) {\n transferAllowances[src][spender] = allowanceNew;\n }\n\n /* We emit a Transfer event */\n emit Transfer(src, dst, tokens);\n\n comptroller.transferVerify(address(this), src, dst, tokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\n }\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n return mintFresh(msg.sender, mintAmount);\n }\n\n /**\n * @notice User supplies assets into the market and receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param minter The address of the account which is supplying the assets\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\n /* Fail if mint not allowed */\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\n }\n\n MintLocalVars memory vars;\n\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the minter and the mintAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\n vars.actualMintAmount,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n /*\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[minter] = vars.accountTokensNew;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\n emit Transfer(address(this), minter, vars.mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\n\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver The address of the account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\n }\n // mintBelahfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\n }\n\n /**\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param payer The address of the account which is paying the underlying token\n * @param receiver The address of the account which is receiving vToken\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\n ensureNonZeroAddress(receiver);\n /* Fail if mint not allowed */\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\n }\n\n MintLocalVars memory vars;\n\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the payer and the mintAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\n vars.actualMintAmount,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n /*\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[receiver] + mintTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[receiver] = vars.accountTokensNew;\n\n /* We emit a MintBehalf event, and a Transfer event */\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\n emit Transfer(address(this), receiver, vars.mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\n\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemInternal(uint redeemTokens) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\n return redeemFresh(msg.sender, redeemTokens, 0);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\n return redeemFresh(msg.sender, 0, redeemAmount);\n }\n\n /**\n * @notice User redeems vTokens in exchange for the underlying asset\n * @dev Assumes interest has already been accrued up to the current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // solhint-disable-next-line code-complexity\n function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal returns (uint) {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n RedeemLocalVars memory vars;\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n ensureNoMathError(vars.mathErr);\n\n /* If redeemTokensIn > 0: */\n if (redeemTokensIn > 0) {\n /*\n * We calculate the exchange rate and the amount of underlying to be redeemed:\n * redeemTokens = redeemTokensIn\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\n */\n vars.redeemTokens = redeemTokensIn;\n\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\n Exp({ mantissa: vars.exchangeRateMantissa }),\n redeemTokensIn\n );\n ensureNoMathError(vars.mathErr);\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n * redeemAmount = redeemAmountIn\n */\n\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\n redeemAmountIn,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n vars.redeemAmount = redeemAmountIn;\n }\n\n /* Fail if redeem not allowed */\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\n if (allowed != 0) {\n revert(\"math error\");\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n revert(\"math error\");\n }\n\n /*\n * We calculate the new total supply and redeemer balance, checking for underflow:\n * totalSupplyNew = totalSupply - redeemTokens\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\n ensureNoMathError(vars.mathErr);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (getCashPrior() < vars.redeemAmount) {\n revert(\"math error\");\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[redeemer] = vars.accountTokensNew;\n\n /*\n * We invoke doTransferOut for the redeemer and the redeemAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken has redeemAmount less of cash.\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n\n uint feeAmount;\n uint remainedAmount;\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\n (vars.mathErr, feeAmount) = mulUInt(\n vars.redeemAmount,\n IComptroller(address(comptroller)).treasuryPercent()\n );\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, feeAmount) = divUInt(feeAmount, 1e18);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\n ensureNoMathError(vars.mathErr);\n\n doTransferOut(address(uint160(IComptroller(address(comptroller)).treasuryAddress())), feeAmount);\n\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\n } else {\n remainedAmount = vars.redeemAmount;\n }\n\n doTransferOut(redeemer, remainedAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), vars.redeemTokens);\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Receiver gets the borrow on behalf of the borrower address\n * @param borrower The borrower, on behalf of whom to borrow\n * @param receiver The account that would receive the funds (can be the same as the borrower)\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function borrowInternal(\n address borrower,\n address payable receiver,\n uint borrowAmount\n ) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\n }\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n return borrowFresh(borrower, receiver, borrowAmount);\n }\n\n /**\n * @notice Receiver gets the borrow on behalf of the borrower address\n * @dev Before calling this function, ensure that the interest has been accrued\n * @param borrower The borrower, on behalf of whom to borrow\n * @param receiver The account that would receive the funds (can be the same as the borrower)\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\n */\n function borrowFresh(address borrower, address payable receiver, uint borrowAmount) internal returns (uint) {\n /* Revert if borrow not allowed */\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\n if (allowed != 0) {\n revert(\"math error\");\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n revert(\"math error\");\n }\n\n /* Revert if protocol has insufficient underlying cash */\n if (getCashPrior() < borrowAmount) {\n revert(\"math error\");\n }\n\n BorrowLocalVars memory vars;\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowsNew = accountBorrows + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\n ensureNoMathError(vars.mathErr);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /*\n * We invoke doTransferOut for the borrower and the borrowAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken borrowAmount less of cash.\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n doTransferOut(receiver, borrowAmount);\n\n /* We emit a Borrow event */\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\n }\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrowing account\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\n }\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\n }\n\n /**\n * @notice Borrows are repaid by another user (possibly the borrower).\n * @param payer The account paying off the borrow\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount of undelrying tokens being returned\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\n /* Fail if repayBorrow not allowed */\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\n if (allowed != 0) {\n return (\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\n 0\n );\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\n }\n\n RepayBorrowLocalVars memory vars;\n\n /* We remember the original borrowerIndex for verification purposes */\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n if (vars.mathErr != MathError.NO_ERROR) {\n return (\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n uint(vars.mathErr)\n ),\n 0\n );\n }\n\n /* If repayAmount == -1, repayAmount = accountBorrows */\n if (repayAmount == uint(-1)) {\n vars.repayAmount = vars.accountBorrows;\n } else {\n vars.repayAmount = repayAmount;\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call doTransferIn for the payer and the repayAmount\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken holds an additional repayAmount of cash.\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\n\n /*\n * We calculate the new borrower and total borrow balances, failing on underflow:\n * accountBorrowsNew = accountBorrows - actualRepayAmount\n * totalBorrowsNew = totalBorrows - actualRepayAmount\n */\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\n ensureNoMathError(vars.mathErr);\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\n\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function liquidateBorrowInternal(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\n }\n\n error = vTokenCollateral.accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\n }\n\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n // solhint-disable-next-line code-complexity\n function liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) internal returns (uint, uint) {\n /* Fail if liquidate not allowed */\n uint allowed = comptroller.liquidateBorrowAllowed(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n repayAmount\n );\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\n }\n\n /* Fail if repayAmount = -1 */\n if (repayAmount == uint(-1)) {\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n /* Fail if repayBorrow fails */\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\n if (repayBorrowError != uint(Error.NO_ERROR)) {\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(amountSeizeError == uint(Error.NO_ERROR), \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"LIQUIDATE_SEIZE_TOO_MUCH\");\n\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\n uint seizeError;\n if (address(vTokenCollateral) == address(this)) {\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\n } else {\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\n require(seizeError == uint(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.liquidateBorrowVerify(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n actualRepayAmount,\n seizeTokens\n );\n\n return (uint(Error.NO_ERROR), actualRepayAmount);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function seizeInternal(\n address seizerToken,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) internal returns (uint) {\n /* Fail if seize not allowed */\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\n if (allowed != 0) {\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\n }\n\n MathError mathErr;\n uint borrowerTokensNew;\n uint liquidatorTokensNew;\n\n /*\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\n */\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\n if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\n }\n\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\n if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accountTokens[borrower] = borrowerTokensNew;\n accountTokens[liquidator] = liquidatorTokensNew;\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, seizeTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\n * @dev Governance function to set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\n // Verify market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\n }\n\n uint oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\n * @param addAmount Amount of addition to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\n (error, ) = _addReservesFresh(addAmount);\n return error;\n }\n\n /**\n * @notice Add reserves by transferring from caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\n */\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\n // totalReserves + actualAddAmount\n uint totalReservesNew;\n uint actualAddAmount;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call doTransferIn for the caller and the addAmount\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken holds an additional addAmount of cash.\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n\n actualAddAmount = doTransferIn(msg.sender, addAmount);\n\n totalReservesNew = totalReserves + actualAddAmount;\n\n /* Revert on overflow */\n require(totalReservesNew >= totalReserves, \"add reserves unexpected overflow\");\n\n // Store reserves[n+1] = reserves[n] + actualAddAmount\n totalReserves = totalReservesNew;\n\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n /* Return (NO_ERROR, actualAddAmount) */\n return (uint(Error.NO_ERROR), actualAddAmount);\n }\n\n /**\n * @notice Reduces reserves by transferring to protocol share reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReservesFresh(uint reduceAmount) internal returns (uint) {\n if (reduceAmount == 0) {\n return uint(Error.NO_ERROR);\n }\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (getCashPrior() < reduceAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n // totalReserves - reduceAmount\n uint totalReservesNew = totalReserves - reduceAmount;\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n doTransferOut(protocolShareReserve, reduceAmount);\n\n IProtocolShareReserveV5(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserveV5.IncomeType.SPREAD\n );\n\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice updates the interest rate model (requires fresh interest accrual)\n * @dev Governance function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\n // Used to store old model for use in the event that is emitted on success\n InterestRateModel oldInterestRateModel;\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\n }\n\n // Track the market's current interest rate model\n oldInterestRateModel = interestRateModel;\n\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n require(newInterestRateModel.isInterestRateModel(), \"marker method returned false\");\n\n // Set the interest rate model to newInterestRateModel\n interestRateModel = newInterestRateModel;\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\n\n return uint(Error.NO_ERROR);\n }\n\n /*** Safe Token ***/\n\n /**\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\n * This may revert due to insufficient balance or insufficient allowance.\n */\n function doTransferIn(address from, uint amount) internal returns (uint);\n\n /**\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\n */\n function doTransferOut(address payable to, uint amount) internal;\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\n */\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\n /* Note: we do not assert that the market is up to date */\n MathError mathErr;\n uint principalTimesIndex;\n uint result;\n\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\n\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n */\n if (borrowSnapshot.principal == 0) {\n return (MathError.NO_ERROR, 0);\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n return (MathError.NO_ERROR, result);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the vToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\n */\n function exchangeRateStoredInternal() internal view returns (MathError, uint) {\n uint _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\n } else {\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\n */\n uint totalCash = getCashPrior();\n uint cashPlusBorrowsMinusReserves;\n Exp memory exchangeRate;\n MathError mathErr;\n\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n return (MathError.NO_ERROR, exchangeRate.mantissa);\n }\n }\n\n function ensureAllowed(string memory functionSig) private view {\n require(\n IAccessControlManagerV5(accessControlManager).isAllowedToCall(msg.sender, functionSig),\n \"access denied\"\n );\n }\n\n function ensureAdmin(address caller_) private view {\n require(caller_ == admin, \"Unauthorized\");\n }\n\n function ensureNoMathError(MathError mErr) private pure {\n require(mErr == MathError.NO_ERROR, \"math error\");\n }\n\n function ensureNonZeroAddress(address address_) private pure {\n require(address_ != address(0), \"zero address\");\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying owned by this contract\n */\n function getCashPrior() internal view returns (uint);\n}\n" + }, + "contracts/Tokens/VTokens/VTokenInterfaces.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Comptroller/ComptrollerInterface.sol\";\nimport \"../../InterestRateModels/InterestRateModel.sol\";\n\ninterface IProtocolShareReserveV5 {\n enum IncomeType {\n SPREAD,\n LIQUIDATION\n }\n\n function updateAssetsState(address comptroller, address asset, IncomeType kind) external;\n}\n\ncontract VTokenStorageBase {\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\n */\n struct BorrowSnapshot {\n uint principal;\n uint interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice EIP-20 token name for this token\n */\n string public name;\n\n /**\n * @notice EIP-20 token symbol for this token\n */\n string public symbol;\n\n /**\n * @notice EIP-20 token decimals for this token\n */\n uint8 public decimals;\n\n /**\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\n */\n\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice Maximum fraction of interest that can be set aside for reserves\n */\n uint internal constant reserveFactorMaxMantissa = 1e18;\n\n /**\n * @notice Administrator for this contract\n */\n address payable public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address payable public pendingAdmin;\n\n /**\n * @notice Contract which oversees inter-vToken operations\n */\n ComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\n InterestRateModel public interestRateModel;\n\n /**\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n uint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @notice Official record of token balances for each account\n */\n mapping(address => uint) internal accountTokens;\n\n /**\n * @notice Approved token transfer amounts on behalf of others\n */\n mapping(address => mapping(address => uint)) internal transferAllowances;\n\n /**\n * @notice Mapping of account addresses to outstanding borrow balances\n */\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\n\n /**\n * @notice Implementation address for this contract\n */\n address public implementation;\n\n /**\n * @notice delta block after which reserves will be reduced\n */\n uint public reduceReservesBlockDelta;\n\n /**\n * @notice last block number at which reserves were reduced\n */\n uint public reduceReservesBlockNumber;\n\n /**\n * @notice address of protocol share reserve contract\n */\n address payable public protocolShareReserve;\n\n /**\n * @notice address of accessControlManager\n */\n\n address public accessControlManager;\n}\n\ncontract VTokenStorage is VTokenStorageBase {\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n\ncontract VTokenInterface is VTokenStorage {\n /**\n * @notice Indicator that this is a vToken contract (for inspection)\n */\n bool public constant isVToken = true;\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are minted behalf by payer to receiver\n */\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are redeemed and fee is transferred\n */\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address liquidator,\n address borrower,\n uint repayAmount,\n address vTokenCollateral,\n uint seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint amount);\n\n /**\n * @notice Event emitted when block delta for reduce reserves get updated\n */\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\n\n /**\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Failure event\n */\n event Failure(uint error, uint info, uint detail);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\n\n /*** User Interface ***/\n\n function transfer(address dst, uint amount) external returns (bool);\n\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n\n function approve(address spender, uint amount) external returns (bool);\n\n function balanceOfUnderlying(address owner) external returns (uint);\n\n function totalBorrowsCurrent() external returns (uint);\n\n function borrowBalanceCurrent(address account) external returns (uint);\n\n function seize(address liquidator, address borrower, uint seizeTokens) external returns (uint);\n\n /*** Admin Function ***/\n function _setPendingAdmin(address payable newPendingAdmin) external returns (uint);\n\n /*** Admin Function ***/\n function _acceptAdmin() external returns (uint);\n\n /*** Admin Function ***/\n function _setReserveFactor(uint newReserveFactorMantissa) external returns (uint);\n\n /*** Admin Function ***/\n function _reduceReserves(uint reduceAmount) external returns (uint);\n\n function balanceOf(address owner) external view returns (uint);\n\n function allowance(address owner, address spender) external view returns (uint);\n\n function getAccountSnapshot(address account) external view returns (uint, uint, uint, uint);\n\n function borrowRatePerBlock() external view returns (uint);\n\n function supplyRatePerBlock() external view returns (uint);\n\n function getCash() external view returns (uint);\n\n function exchangeRateCurrent() public returns (uint);\n\n function accrueInterest() public returns (uint);\n\n /*** Admin Function ***/\n function _setComptroller(ComptrollerInterface newComptroller) public returns (uint);\n\n /*** Admin Function ***/\n function _setInterestRateModel(InterestRateModel newInterestRateModel) public returns (uint);\n\n function borrowBalanceStored(address account) public view returns (uint);\n\n function exchangeRateStored() public view returns (uint);\n}\n\ncontract VBep20Interface {\n /*** User Interface ***/\n\n function mint(uint mintAmount) external returns (uint);\n\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\n\n function redeem(uint redeemTokens) external returns (uint);\n\n function redeemUnderlying(uint redeemAmount) external returns (uint);\n\n function borrow(uint borrowAmount) external returns (uint);\n\n function repayBorrow(uint repayAmount) external returns (uint);\n\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\n\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint);\n\n /*** Admin Functions ***/\n\n function _addReserves(uint addAmount) external returns (uint);\n}\n\ncontract VDelegatorInterface {\n /**\n * @notice Emitted when implementation is changed\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) public;\n}\n\ncontract VDelegateInterface {\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @dev Should revert if any issues arise which make it unfit for delegation\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) public;\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() public;\n}\n" + }, + "contracts/Tokens/XVS/IXVSVesting.sol": { + "content": "pragma solidity ^0.5.16;\n\ninterface IXVSVesting {\n /// @param _recipient Address of the Vesting. recipient entitled to claim the vested funds\n /// @param _amount Total number of tokens Vested\n function deposit(address _recipient, uint256 _amount) external;\n}\n" + }, + "contracts/Tokens/XVS/XVS.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Utils/Tokenlock.sol\";\n\ncontract XVS is Tokenlock {\n /// @notice BEP-20 token name for this token\n string public constant name = \"Venus\";\n\n /// @notice BEP-20 token symbol for this token\n string public constant symbol = \"XVS\";\n\n /// @notice BEP-20 token decimals for this token\n uint8 public constant decimals = 18;\n\n /// @notice Total number of tokens in circulation\n uint public constant totalSupply = 30000000e18; // 30 million XVS\n\n /// @notice Allowance amounts on behalf of others\n mapping(address => mapping(address => uint96)) internal allowances;\n\n /// @notice Official record of token balances for each account\n mapping(address => uint96) internal balances;\n\n /// @notice A record of each accounts delegate\n mapping(address => address) public delegates;\n\n /// @notice A checkpoint for marking number of votes from a given block\n struct Checkpoint {\n uint32 fromBlock;\n uint96 votes;\n }\n\n /// @notice A record of votes checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH =\n keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /// @notice An event thats emitted when an account changes its delegate\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /// @notice An event thats emitted when a delegate account's vote balance changes\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\n\n /// @notice The standard BEP-20 transfer event\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @notice The standard BEP-20 approval event\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Construct a new XVS token\n * @param account The initial account to grant all the tokens\n */\n constructor(address account) public {\n balances[account] = uint96(totalSupply);\n emit Transfer(address(0), account, totalSupply);\n }\n\n /**\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\n * @param account The address of the account holding the funds\n * @param spender The address of the account spending the funds\n * @return The number of tokens approved\n */\n function allowance(address account, address spender) external view returns (uint) {\n return allowances[account][spender];\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint rawAmount) external validLock returns (bool) {\n uint96 amount;\n if (rawAmount == uint(-1)) {\n amount = uint96(-1);\n } else {\n amount = safe96(rawAmount, \"XVS::approve: amount exceeds 96 bits\");\n }\n\n allowances[msg.sender][spender] = amount;\n\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n /**\n * @notice Get the number of tokens held by the `account`\n * @param account The address of the account to get the balance of\n * @return The number of tokens held\n */\n function balanceOf(address account) external view returns (uint) {\n return balances[account];\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint rawAmount) external validLock returns (bool) {\n uint96 amount = safe96(rawAmount, \"XVS::transfer: amount exceeds 96 bits\");\n _transferTokens(msg.sender, dst, amount);\n return true;\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint rawAmount) external validLock returns (bool) {\n address spender = msg.sender;\n uint96 spenderAllowance = allowances[src][spender];\n uint96 amount = safe96(rawAmount, \"XVS::approve: amount exceeds 96 bits\");\n\n if (spender != src && spenderAllowance != uint96(-1)) {\n uint96 newAllowance = sub96(\n spenderAllowance,\n amount,\n \"XVS::transferFrom: transfer amount exceeds spender allowance\"\n );\n allowances[src][spender] = newAllowance;\n\n emit Approval(src, spender, newAllowance);\n }\n\n _transferTokens(src, dst, amount);\n return true;\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) public validLock {\n return _delegate(msg.sender, delegatee);\n }\n\n /**\n * @notice Delegates votes from signatory to `delegatee`\n * @param delegatee The address to delegate votes to\n * @param nonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v The recovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public validLock {\n bytes32 domainSeparator = keccak256(\n abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this))\n );\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n address signatory = ecrecover(digest, v, r, s);\n require(signatory != address(0), \"XVS::delegateBySig: invalid signature\");\n require(nonce == nonces[signatory]++, \"XVS::delegateBySig: invalid nonce\");\n require(now <= expiry, \"XVS::delegateBySig: signature expired\");\n return _delegate(signatory, delegatee);\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getCurrentVotes(address account) external view returns (uint96) {\n uint32 nCheckpoints = numCheckpoints[account];\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n }\n\n /**\n * @notice Determine the prior number of votes for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param blockNumber The block number to get the vote balance at\n * @return The number of votes the account had as of the given block\n */\n function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\n require(blockNumber < block.number, \"XVS::getPriorVotes: not yet determined\");\n\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\n return checkpoints[account][nCheckpoints - 1].votes;\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].fromBlock > blockNumber) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.fromBlock == blockNumber) {\n return cp.votes;\n } else if (cp.fromBlock < blockNumber) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return checkpoints[account][lower].votes;\n }\n\n function _delegate(address delegator, address delegatee) internal {\n address currentDelegate = delegates[delegator];\n uint96 delegatorBalance = balances[delegator];\n delegates[delegator] = delegatee;\n\n emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _transferTokens(address src, address dst, uint96 amount) internal {\n require(src != address(0), \"XVS::_transferTokens: cannot transfer from the zero address\");\n require(dst != address(0), \"XVS::_transferTokens: cannot transfer to the zero address\");\n\n balances[src] = sub96(balances[src], amount, \"XVS::_transferTokens: transfer amount exceeds balance\");\n balances[dst] = add96(balances[dst], amount, \"XVS::_transferTokens: transfer amount overflows\");\n emit Transfer(src, dst, amount);\n\n _moveDelegates(delegates[src], delegates[dst], amount);\n }\n\n function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {\n if (srcRep != dstRep && amount > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\n uint96 srcRepNew = sub96(srcRepOld, amount, \"XVS::_moveVotes: vote amount underflows\");\n _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\n uint96 dstRepNew = add96(dstRepOld, amount, \"XVS::_moveVotes: vote amount overflows\");\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n }\n }\n }\n\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\n uint32 blockNumber = safe32(block.number, \"XVS::_writeCheckpoint: block number exceeds 32 bits\");\n\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n } else {\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\n numCheckpoints[delegatee] = nCheckpoints + 1;\n }\n\n emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n }\n\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n require(n < 2 ** 32, errorMessage);\n return uint32(n);\n }\n\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\n require(n < 2 ** 96, errorMessage);\n return uint96(n);\n }\n\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n uint96 c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function getChainId() internal pure returns (uint) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n return chainId;\n }\n}\n" + }, + "contracts/Tokens/XVS/XVSVesting.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Utils/IBEP20.sol\";\nimport \"../../Utils/SafeBEP20.sol\";\nimport \"./XVSVestingStorage.sol\";\nimport \"./XVSVestingProxy.sol\";\n\n/**\n * @title Venus's XVSVesting Contract\n * @author Venus\n */\ncontract XVSVesting is XVSVestingStorage {\n using SafeMath for uint256;\n using SafeBEP20 for IBEP20;\n\n /// @notice total vesting period for 1 year in seconds\n uint256 public constant TOTAL_VESTING_TIME = 365 * 24 * 60 * 60;\n\n /// @notice decimal precision for XVS\n uint256 public constant xvsDecimalsMultiplier = 1e18;\n\n /// @notice Emitted when XVSVested is claimed by recipient\n event VestedTokensClaimed(address recipient, uint256 amountClaimed);\n\n /// @notice Emitted when vrtConversionAddress is set\n event VRTConversionSet(address vrtConversionAddress);\n\n /// @notice Emitted when XVS is deposited for vesting\n event XVSVested(address indexed recipient, uint256 startTime, uint256 amount, uint256 withdrawnAmount);\n\n /// @notice Emitted when XVS is withdrawn by recipient\n event XVSWithdrawn(address recipient, uint256 amount);\n\n modifier nonZeroAddress(address _address) {\n require(_address != address(0), \"Address cannot be Zero\");\n _;\n }\n\n constructor() public {}\n\n /**\n * @notice initialize XVSVestingStorage\n * @param _xvsAddress The XVSToken address\n */\n function initialize(address _xvsAddress) public {\n require(msg.sender == admin, \"only admin may initialize the XVSVesting\");\n require(initialized == false, \"XVSVesting is already initialized\");\n require(_xvsAddress != address(0), \"_xvsAddress cannot be Zero\");\n xvs = IBEP20(_xvsAddress);\n\n _notEntered = true;\n initialized = true;\n }\n\n modifier isInitialized() {\n require(initialized == true, \"XVSVesting is not initialized\");\n _;\n }\n\n /**\n * @notice sets VRTConverter Address\n * @dev Note: If VRTConverter is not set, then Vesting is not allowed\n * @param _vrtConversionAddress The VRTConverterProxy Address\n */\n function setVRTConverter(address _vrtConversionAddress) public {\n require(msg.sender == admin, \"only admin may initialize the Vault\");\n require(_vrtConversionAddress != address(0), \"vrtConversionAddress cannot be Zero\");\n vrtConversionAddress = _vrtConversionAddress;\n emit VRTConversionSet(_vrtConversionAddress);\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin can\");\n _;\n }\n\n modifier onlyVrtConverter() {\n require(msg.sender == vrtConversionAddress, \"only VRTConversion Address can call the function\");\n _;\n }\n\n modifier vestingExistCheck(address recipient) {\n require(vestings[recipient].length > 0, \"recipient doesnot have any vestingRecord\");\n _;\n }\n\n /**\n * @notice Deposit XVS for Vesting\n * @param recipient The vesting recipient\n * @param depositAmount XVS amount for deposit\n */\n function deposit(\n address recipient,\n uint depositAmount\n ) external isInitialized onlyVrtConverter nonZeroAddress(recipient) {\n require(depositAmount > 0, \"Deposit amount must be non-zero\");\n\n VestingRecord[] storage vestingsOfRecipient = vestings[recipient];\n\n VestingRecord memory vesting = VestingRecord({\n recipient: recipient,\n startTime: getCurrentTime(),\n amount: depositAmount,\n withdrawnAmount: 0\n });\n\n vestingsOfRecipient.push(vesting);\n\n emit XVSVested(recipient, vesting.startTime, vesting.amount, vesting.withdrawnAmount);\n }\n\n /**\n * @notice Withdraw Vested XVS of recipient\n */\n function withdraw() external isInitialized vestingExistCheck(msg.sender) {\n address recipient = msg.sender;\n VestingRecord[] storage vestingsOfRecipient = vestings[recipient];\n uint256 vestingCount = vestingsOfRecipient.length;\n uint256 totalWithdrawableAmount = 0;\n\n for (uint i = 0; i < vestingCount; ++i) {\n VestingRecord storage vesting = vestingsOfRecipient[i];\n (, uint256 toWithdraw) = calculateWithdrawableAmount(\n vesting.amount,\n vesting.startTime,\n vesting.withdrawnAmount\n );\n if (toWithdraw > 0) {\n totalWithdrawableAmount = totalWithdrawableAmount.add(toWithdraw);\n vesting.withdrawnAmount = vesting.withdrawnAmount.add(toWithdraw);\n }\n }\n\n if (totalWithdrawableAmount > 0) {\n uint256 xvsBalance = xvs.balanceOf(address(this));\n require(xvsBalance >= totalWithdrawableAmount, \"Insufficient XVS for withdrawal\");\n emit XVSWithdrawn(recipient, totalWithdrawableAmount);\n xvs.safeTransfer(recipient, totalWithdrawableAmount);\n }\n }\n\n /**\n * @notice get Withdrawable XVS Amount\n * @param recipient The vesting recipient\n * @dev returns A tuple with totalWithdrawableAmount , totalVestedAmount and totalWithdrawnAmount\n */\n function getWithdrawableAmount(\n address recipient\n )\n public\n view\n isInitialized\n nonZeroAddress(recipient)\n vestingExistCheck(recipient)\n returns (uint256 totalWithdrawableAmount, uint256 totalVestedAmount, uint256 totalWithdrawnAmount)\n {\n VestingRecord[] storage vestingsOfRecipient = vestings[recipient];\n uint256 vestingCount = vestingsOfRecipient.length;\n\n for (uint i = 0; i < vestingCount; i++) {\n VestingRecord storage vesting = vestingsOfRecipient[i];\n (uint256 vestedAmount, uint256 toWithdraw) = calculateWithdrawableAmount(\n vesting.amount,\n vesting.startTime,\n vesting.withdrawnAmount\n );\n totalVestedAmount = totalVestedAmount.add(vestedAmount);\n totalWithdrawableAmount = totalWithdrawableAmount.add(toWithdraw);\n totalWithdrawnAmount = totalWithdrawnAmount.add(vesting.withdrawnAmount);\n }\n\n return (totalWithdrawableAmount, totalVestedAmount, totalWithdrawnAmount);\n }\n\n /**\n * @notice get Withdrawable XVS Amount\n * @param amount Amount deposited for vesting\n * @param vestingStartTime time in epochSeconds at the time of vestingDeposit\n * @param withdrawnAmount XVSAmount withdrawn from VestedAmount\n * @dev returns A tuple with vestedAmount and withdrawableAmount\n */\n function calculateWithdrawableAmount(\n uint256 amount,\n uint256 vestingStartTime,\n uint256 withdrawnAmount\n ) internal view returns (uint256, uint256) {\n uint256 vestedAmount = calculateVestedAmount(amount, vestingStartTime, getCurrentTime());\n uint toWithdraw = vestedAmount.sub(withdrawnAmount);\n return (vestedAmount, toWithdraw);\n }\n\n /**\n * @notice calculate total vested amount\n * @param vestingAmount Amount deposited for vesting\n * @param vestingStartTime time in epochSeconds at the time of vestingDeposit\n * @param currentTime currentTime in epochSeconds\n * @return Total XVS amount vested\n */\n function calculateVestedAmount(\n uint256 vestingAmount,\n uint256 vestingStartTime,\n uint256 currentTime\n ) internal view returns (uint256) {\n if (currentTime < vestingStartTime) {\n return 0;\n } else if (currentTime > vestingStartTime.add(TOTAL_VESTING_TIME)) {\n return vestingAmount;\n } else {\n return (vestingAmount.mul(currentTime.sub(vestingStartTime))).div(TOTAL_VESTING_TIME);\n }\n }\n\n /**\n * @notice current block timestamp\n * @return blocktimestamp\n */\n function getCurrentTime() public view returns (uint256) {\n return block.timestamp;\n }\n\n /*** Admin Functions ***/\n function _become(XVSVestingProxy xvsVestingProxy) public {\n require(msg.sender == xvsVestingProxy.admin(), \"only proxy admin can change brains\");\n xvsVestingProxy._acceptImplementation();\n }\n}\n" + }, + "contracts/Tokens/XVS/XVSVestingProxy.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./XVSVestingStorage.sol\";\n\ncontract XVSVestingProxy is XVSVestingAdminStorage {\n /**\n * @notice Emitted when pendingImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingImplementation is accepted, which means XVSVesting implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor(\n address implementation_,\n address _xvsAddress\n ) public nonZeroAddress(implementation_) nonZeroAddress(_xvsAddress) {\n // Creator of the contract is admin during initialization\n admin = msg.sender;\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_);\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(implementation_, abi.encodeWithSignature(\"initialize(address)\", _xvsAddress));\n }\n\n modifier nonZeroAddress(address _address) {\n require(_address != address(0), \"Address cannot be Zero\");\n _;\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n */\n function _setImplementation(address implementation_) public {\n require(msg.sender == admin, \"XVSVestingProxy::_setImplementation: admin only\");\n require(implementation_ != address(0), \"XVSVestingProxy::_setImplementation: invalid implementation address\");\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal nonZeroAddress(callee) returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n return returnData;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(\n address newPendingImplementation\n ) public nonZeroAddress(newPendingImplementation) {\n require(msg.sender == admin, \"Only admin can set Pending Implementation\");\n\n address oldPendingImplementation = pendingImplementation;\n\n pendingImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingImplementation);\n }\n\n /**\n * @notice Accepts new implementation of VRT Vault. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n */\n function _acceptImplementation() public {\n // Check caller is pendingImplementation\n require(\n msg.sender == pendingImplementation,\n \"only address marked as pendingImplementation can accept Implementation\"\n );\n\n // Save current values for inclusion in log\n address oldImplementation = implementation;\n address oldPendingImplementation = pendingImplementation;\n\n implementation = pendingImplementation;\n\n pendingImplementation = address(0);\n\n emit NewImplementation(oldImplementation, implementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingImplementation);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n */\n function _setPendingAdmin(address newPendingAdmin) public nonZeroAddress(newPendingAdmin) {\n // Check caller = admin\n require(msg.sender == admin, \"only admin can set pending admin\");\n require(newPendingAdmin != pendingAdmin, \"New pendingAdmin can not be same as the previous one\");\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n */\n function _acceptAdmin() public {\n // Check caller is pendingAdmin\n require(msg.sender == pendingAdmin, \"only address marked as pendingAdmin can accept as Admin\");\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n function() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/Tokens/XVS/XVSVestingStorage.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../../Utils/SafeMath.sol\";\nimport \"../../Utils/IBEP20.sol\";\n\ncontract XVSVestingAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of XVSVesting\n */\n address public implementation;\n\n /**\n * @notice Pending brains of XVSVesting\n */\n address public pendingImplementation;\n}\n\ncontract XVSVestingStorage is XVSVestingAdminStorage {\n struct VestingRecord {\n address recipient;\n uint256 startTime;\n uint256 amount;\n uint256 withdrawnAmount;\n }\n\n /// @notice Guard variable for re-entrancy checks\n bool public _notEntered;\n\n /// @notice indicator to check if the contract is initialized\n bool public initialized;\n\n /// @notice The XVS TOKEN!\n IBEP20 public xvs;\n\n /// @notice VRTConversion Contract Address\n address public vrtConversionAddress;\n\n /// @notice mapping of VestingRecord(s) for user(s)\n mapping(address => VestingRecord[]) public vestings;\n}\n" + }, + "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 {\n codehash := extcodehash(account)\n }\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 // solium-disable-next-line security/no-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/CarefulMath.sol": { + "content": "pragma solidity ^0.5.16;\n\n/**\n * @title Careful Math\n * @author Venus\n * @notice Derived from OpenZeppelin's SafeMath library\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\n */\ncontract CarefulMath {\n /**\n * @dev Possible error codes that we can return\n */\n enum MathError {\n NO_ERROR,\n DIVISION_BY_ZERO,\n INTEGER_OVERFLOW,\n INTEGER_UNDERFLOW\n }\n\n /**\n * @dev Multiplies two numbers, returns an error on overflow.\n */\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (a == 0) {\n return (MathError.NO_ERROR, 0);\n }\n\n uint c = a * b;\n\n if (c / a != b) {\n return (MathError.INTEGER_OVERFLOW, 0);\n } else {\n return (MathError.NO_ERROR, c);\n }\n }\n\n /**\n * @dev Integer division of two numbers, truncating the quotient.\n */\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (b == 0) {\n return (MathError.DIVISION_BY_ZERO, 0);\n }\n\n return (MathError.NO_ERROR, a / b);\n }\n\n /**\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\n */\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (b <= a) {\n return (MathError.NO_ERROR, a - b);\n } else {\n return (MathError.INTEGER_UNDERFLOW, 0);\n }\n }\n\n /**\n * @dev Adds two numbers, returns an error on overflow.\n */\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\n uint c = a + b;\n\n if (c >= a) {\n return (MathError.NO_ERROR, c);\n } else {\n return (MathError.INTEGER_OVERFLOW, 0);\n }\n }\n\n /**\n * @dev add a and b and then subtract c\n */\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\n (MathError err0, uint sum) = addUInt(a, b);\n\n if (err0 != MathError.NO_ERROR) {\n return (err0, 0);\n }\n\n return subUInt(sum, c);\n }\n}\n" + }, + "contracts/Utils/Context.sol": { + "content": "pragma solidity ^0.5.16;\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\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" + }, + "contracts/Utils/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// Adapted from OpenZeppelin Contracts v4.3.2 (utils/cryptography/ECDSA.sol)\n\n// SPDX-Copyright-Text: OpenZeppelin, 2021\n// SPDX-Copyright-Text: Venus, 2021\n\npragma solidity ^0.5.16;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\ncontract ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 && v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n}\n" + }, + "contracts/Utils/ErrorReporter.sol": { + "content": "pragma solidity ^0.5.16;\n\ncontract ComptrollerErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED,\n COMPTROLLER_MISMATCH,\n INSUFFICIENT_SHORTFALL,\n INSUFFICIENT_LIQUIDITY,\n INVALID_CLOSE_FACTOR,\n INVALID_COLLATERAL_FACTOR,\n INVALID_LIQUIDATION_INCENTIVE,\n MARKET_NOT_ENTERED, // no longer possible\n MARKET_NOT_LISTED,\n MARKET_ALREADY_LISTED,\n MATH_ERROR,\n NONZERO_BORROW_BALANCE,\n PRICE_ERROR,\n REJECTION,\n SNAPSHOT_ERROR,\n TOO_MANY_ASSETS,\n TOO_MUCH_REPAY,\n INSUFFICIENT_BALANCE_FOR_VAI,\n MARKET_NOT_COLLATERAL\n }\n\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n EXIT_MARKET_BALANCE_OWED,\n EXIT_MARKET_REJECTION,\n SET_CLOSE_FACTOR_OWNER_CHECK,\n SET_CLOSE_FACTOR_VALIDATION,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_NO_EXISTS,\n SET_COLLATERAL_FACTOR_VALIDATION,\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\n SET_IMPLEMENTATION_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\n SET_PRICE_ORACLE_OWNER_CHECK,\n SUPPORT_MARKET_EXISTS,\n SUPPORT_MARKET_OWNER_CHECK,\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\n SET_VAI_MINT_RATE_CHECK,\n SET_VAICONTROLLER_OWNER_CHECK,\n SET_MINTED_VAI_REJECTION,\n SET_TREASURY_OWNER_CHECK\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n\ncontract TokenErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED,\n BAD_INPUT,\n COMPTROLLER_REJECTION,\n COMPTROLLER_CALCULATION_ERROR,\n INTEREST_RATE_MODEL_ERROR,\n INVALID_ACCOUNT_PAIR,\n INVALID_CLOSE_AMOUNT_REQUESTED,\n INVALID_COLLATERAL_FACTOR,\n MATH_ERROR,\n MARKET_NOT_FRESH,\n MARKET_NOT_LISTED,\n TOKEN_INSUFFICIENT_ALLOWANCE,\n TOKEN_INSUFFICIENT_BALANCE,\n TOKEN_INSUFFICIENT_CASH,\n TOKEN_TRANSFER_IN_FAILED,\n TOKEN_TRANSFER_OUT_FAILED,\n TOKEN_PRICE_ERROR\n }\n\n /*\n * Note: FailureInfo (but not Error) is kept in alphabetical order\n * This is because FailureInfo grows significantly faster, and\n * the order of Error has some meaning, while the order of FailureInfo\n * is entirely arbitrary.\n */\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n BORROW_ACCRUE_INTEREST_FAILED,\n BORROW_CASH_NOT_AVAILABLE,\n BORROW_FRESHNESS_CHECK,\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n BORROW_MARKET_NOT_LISTED,\n BORROW_COMPTROLLER_REJECTION,\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n LIQUIDATE_COMPTROLLER_REJECTION,\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\n LIQUIDATE_FRESHNESS_CHECK,\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_SEIZE_TOO_MUCH,\n MINT_ACCRUE_INTEREST_FAILED,\n MINT_COMPTROLLER_REJECTION,\n MINT_EXCHANGE_CALCULATION_FAILED,\n MINT_EXCHANGE_RATE_READ_FAILED,\n MINT_FRESHNESS_CHECK,\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n MINT_TRANSFER_IN_FAILED,\n MINT_TRANSFER_IN_NOT_POSSIBLE,\n REDEEM_ACCRUE_INTEREST_FAILED,\n REDEEM_COMPTROLLER_REJECTION,\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\n REDEEM_EXCHANGE_RATE_READ_FAILED,\n REDEEM_FRESHNESS_CHECK,\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\n REDUCE_RESERVES_ADMIN_CHECK,\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\n REDUCE_RESERVES_FRESH_CHECK,\n REDUCE_RESERVES_VALIDATION,\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_COMPTROLLER_REJECTION,\n REPAY_BORROW_FRESHNESS_CHECK,\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_VALIDATION,\n SET_COMPTROLLER_OWNER_CHECK,\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_ORACLE_MARKET_NOT_LISTED,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\n SET_RESERVE_FACTOR_ADMIN_CHECK,\n SET_RESERVE_FACTOR_FRESH_CHECK,\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\n TRANSFER_COMPTROLLER_REJECTION,\n TRANSFER_NOT_ALLOWED,\n TRANSFER_NOT_ENOUGH,\n TRANSFER_TOO_MUCH,\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\n ADD_RESERVES_FRESH_CHECK,\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\n REPAY_VAI_COMPTROLLER_REJECTION,\n REPAY_VAI_FRESHNESS_CHECK,\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n\ncontract VAIControllerErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED, // The sender is not authorized to perform this action.\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\n MATH_ERROR, // A math calculation error occurred.\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\n }\n\n enum FailureInfo {\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\n SET_COMPTROLLER_OWNER_CHECK,\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n VAI_MINT_REJECTION,\n VAI_BURN_REJECTION,\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\n VAI_LIQUIDATE_FRESHNESS_CHECK,\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\n MINT_FEE_CALCULATION_FAILED,\n SET_TREASURY_OWNER_CHECK\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n" + }, + "contracts/Utils/Exponential.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./CarefulMath.sol\";\nimport \"./ExponentialNoError.sol\";\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Venus\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract Exponential is CarefulMath, ExponentialNoError {\n /**\n * @dev Creates an exponential from numerator and denominator values.\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\n * or if `denom` is zero.\n */\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\n }\n\n /**\n * @dev Adds two exponentials, returning a new exponential.\n */\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\n\n return (error, Exp({ mantissa: result }));\n }\n\n /**\n * @dev Subtracts two exponentials, returning a new exponential.\n */\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\n\n return (error, Exp({ mantissa: result }));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, returning a new Exp.\n */\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return (MathError.NO_ERROR, truncate(product));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return addUInt(truncate(product), addend);\n }\n\n /**\n * @dev Divide an Exp by a scalar, returning a new Exp.\n */\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\n }\n\n /**\n * @dev Divide a scalar by an Exp, returning a new Exp.\n */\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\n /*\n We are doing this as:\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\n\n How it works:\n Exp = a / b;\n Scalar = s;\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\n */\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n return getExp(numerator, divisor.mantissa);\n }\n\n /**\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\n */\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return (MathError.NO_ERROR, truncate(fraction));\n }\n\n /**\n * @dev Multiplies two exponentials, returning a new exponential.\n */\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n // We add half the scale before dividing so that we get rounding instead of truncation.\n // See \"Listing 6\" and text above it at https://accu.org/index.php/journals/1717\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({ mantissa: 0 }));\n }\n\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\n assert(err2 == MathError.NO_ERROR);\n\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\n }\n\n /**\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\n */\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\n }\n\n /**\n * @dev Multiplies three exponentials, returning a new exponential.\n */\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\n (MathError err, Exp memory ab) = mulExp(a, b);\n if (err != MathError.NO_ERROR) {\n return (err, ab);\n }\n return mulExp(ab, c);\n }\n\n /**\n * @dev Divides two exponentials, returning a new exponential.\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\n */\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n return getExp(a.mantissa, b.mantissa);\n }\n}\n" + }, + "contracts/Utils/ExponentialNoError.sol": { + "content": "pragma solidity ^0.5.16;\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n uint internal constant expScale = 1e18;\n uint internal constant doubleScale = 1e36;\n uint internal constant halfExpScale = expScale / 2;\n uint internal constant mantissaOne = expScale;\n\n struct Exp {\n uint mantissa;\n }\n\n struct Double {\n uint mantissa;\n }\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / expScale;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\n Exp memory product = mul_(a, scalar);\n return truncate(product);\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n /**\n * @dev Checks if first Exp is less than second Exp.\n */\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa < right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp <= right Exp.\n */\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa <= right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp > right Exp.\n */\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa > right.mantissa;\n }\n\n /**\n * @dev returns true if Exp is exactly zero\n */\n function isZeroExp(Exp memory value) internal pure returns (bool) {\n return value.mantissa == 0;\n }\n\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\n require(n < 2 ** 224, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n require(n < 2 ** 32, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(uint a, uint b) internal pure returns (uint) {\n return add_(a, b, \"addition overflow\");\n }\n\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n uint c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(uint a, uint b) internal pure returns (uint) {\n return sub_(a, b, \"subtraction underflow\");\n }\n\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\n }\n\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\n return mul_(a, b.mantissa) / expScale;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\n }\n\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint a, Double memory b) internal pure returns (uint) {\n return mul_(a, b.mantissa) / doubleScale;\n }\n\n function mul_(uint a, uint b) internal pure returns (uint) {\n return mul_(a, b, \"multiplication overflow\");\n }\n\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n if (a == 0 || b == 0) {\n return 0;\n }\n uint c = a * b;\n require(c / a == b, errorMessage);\n return c;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\n }\n\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint a, Exp memory b) internal pure returns (uint) {\n return div_(mul_(a, expScale), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\n }\n\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint a, Double memory b) internal pure returns (uint) {\n return div_(mul_(a, doubleScale), b.mantissa);\n }\n\n function div_(uint a, uint b) internal pure returns (uint) {\n return div_(a, b, \"divide by zero\");\n }\n\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n function fraction(uint a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\n }\n}\n" + }, + "contracts/Utils/IBEP20.sol": { + "content": "pragma solidity ^0.5.0;\n\n/**\n * @dev Interface of the BEP20 standard as defined in the EIP. Does not include\n * the optional functions; to access them see {BEP20Detailed}.\n */\ninterface IBEP20 {\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" + }, + "contracts/Utils/Ownable.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public onlyOwner {\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n */\n function _transferOwnership(address newOwner) internal {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/Utils/Owned.sol": { + "content": "pragma solidity ^0.5.16;\n\ncontract Owned {\n address public owner;\n\n event OwnershipTransferred(address indexed _from, address indexed _to);\n\n constructor() public {\n owner = msg.sender;\n }\n\n modifier onlyOwner() {\n require(msg.sender == owner, \"Should be owner\");\n _;\n }\n\n function transferOwnership(address newOwner) public onlyOwner {\n owner = newOwner;\n emit OwnershipTransferred(owner, newOwner);\n }\n}\n" + }, + "contracts/Utils/SafeBEP20.sol": { + "content": "pragma solidity ^0.5.0;\n\nimport \"./SafeMath.sol\";\nimport \"./IBEP20.sol\";\nimport \"./Address.sol\";\n\n/**\n * @title SafeBEP20\n * @dev Wrappers around BEP20 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 SafeBEP20 for BEP20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeBEP20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IBEP20 token, address to, uint256 value) internal {\n callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IBEP20 token, address from, address to, uint256 value) internal {\n callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n function safeApprove(IBEP20 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(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeBEP20: approve from non-zero to non-zero allowance\"\n );\n callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IBEP20 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(IBEP20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(\n value,\n \"SafeBEP20: decreased allowance below zero\"\n );\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(IBEP20 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(), \"SafeBEP20: 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, \"SafeBEP20: low-level call failed\");\n\n if (returndata.length > 0) {\n // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeBEP20: BEP20 operation did not succeed\");\n }\n }\n}\n" + }, + "contracts/Utils/SafeCast.sol": { + "content": "pragma solidity ^0.5.16;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an 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 *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value < 2 ** 128, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value < 2 ** 64, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value < 2 ** 32, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value < 2 ** 16, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value < 2 ** 8, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128) {\n require(value >= -2 ** 127 && value < 2 ** 127, \"SafeCast: value doesn't fit in 128 bits\");\n return int128(value);\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64) {\n require(value >= -2 ** 63 && value < 2 ** 63, \"SafeCast: value doesn't fit in 64 bits\");\n return int64(value);\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32) {\n require(value >= -2 ** 31 && value < 2 ** 31, \"SafeCast: value doesn't fit in 32 bits\");\n return int32(value);\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16) {\n require(value >= -2 ** 15 && value < 2 ** 15, \"SafeCast: value doesn't fit in 16 bits\");\n return int16(value);\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8) {\n require(value >= -2 ** 7 && value < 2 ** 7, \"SafeCast: value doesn't fit in 8 bits\");\n return int8(value);\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n require(value < 2 ** 255, \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "contracts/Utils/SafeMath.sol": { + "content": "pragma solidity ^0.5.16;\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 return add(a, b, \"SafeMath: addition 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 function add(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, errorMessage);\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 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 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 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" + }, + "contracts/Utils/Tokenlock.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./Owned.sol\";\n\ncontract Tokenlock is Owned {\n /// @notice Indicates if token is locked\n uint8 internal isLocked = 0;\n\n event Freezed();\n event UnFreezed();\n\n modifier validLock() {\n require(isLocked == 0, \"Token is locked\");\n _;\n }\n\n function freeze() public onlyOwner {\n isLocked = 1;\n\n emit Freezed();\n }\n\n function unfreeze() public onlyOwner {\n isLocked = 0;\n\n emit UnFreezed();\n }\n}\n" + }, + "contracts/VAIVault/VAIVault.sol": { + "content": "pragma solidity 0.5.16;\n\nimport \"../Utils/SafeBEP20.sol\";\nimport \"../Utils/IBEP20.sol\";\nimport \"./VAIVaultStorage.sol\";\nimport \"./VAIVaultErrorReporter.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol\";\nimport { VAIVaultProxy } from \"./VAIVaultProxy.sol\";\n\n/**\n * @title VAI Vault\n * @author Venus\n * @notice The VAI Vault is configured for users to stake VAI And receive XVS as a reward.\n */\ncontract VAIVault is VAIVaultStorage, AccessControlledV5 {\n using SafeMath for uint256;\n using SafeBEP20 for IBEP20;\n\n /// @notice Event emitted when VAI deposit\n event Deposit(address indexed user, uint256 amount);\n\n /// @notice Event emitted when VAI withrawal\n event Withdraw(address indexed user, uint256 amount);\n\n /// @notice Event emitted when vault is paused\n event VaultPaused(address indexed admin);\n\n /// @notice Event emitted when vault is resumed after pause\n event VaultResumed(address indexed admin);\n\n constructor() public {\n admin = msg.sender;\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin can\");\n _;\n }\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n /**\n * @dev Prevents functions to execute when vault is paused.\n */\n modifier isActive() {\n require(!vaultPaused, \"Vault is paused\");\n _;\n }\n\n /**\n * @notice Pause vault\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n require(!vaultPaused, \"Vault is already paused\");\n vaultPaused = true;\n emit VaultPaused(msg.sender);\n }\n\n /**\n * @notice Resume vault\n */\n function resume() external {\n _checkAccessAllowed(\"resume()\");\n require(vaultPaused, \"Vault is not paused\");\n vaultPaused = false;\n emit VaultResumed(msg.sender);\n }\n\n /**\n * @notice Deposit VAI to VAIVault for XVS allocation\n * @param _amount The amount to deposit to vault\n */\n function deposit(uint256 _amount) external nonReentrant isActive {\n UserInfo storage user = userInfo[msg.sender];\n\n updateVault();\n\n // Transfer pending tokens to user\n updateAndPayOutPending(msg.sender);\n\n // Transfer in the amounts from user\n if (_amount > 0) {\n vai.safeTransferFrom(address(msg.sender), address(this), _amount);\n user.amount = user.amount.add(_amount);\n }\n\n user.rewardDebt = user.amount.mul(accXVSPerShare).div(1e18);\n emit Deposit(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraw VAI from VAIVault\n * @param _amount The amount to withdraw from vault\n */\n function withdraw(uint256 _amount) external nonReentrant isActive {\n _withdraw(msg.sender, _amount);\n }\n\n /**\n * @notice Claim XVS from VAIVault\n */\n function claim() external nonReentrant isActive {\n _withdraw(msg.sender, 0);\n }\n\n /**\n * @notice Claim XVS from VAIVault\n * @param account The account for which to claim XVS\n */\n function claim(address account) external nonReentrant isActive {\n _withdraw(account, 0);\n }\n\n /**\n * @notice Low level withdraw function\n * @param account The account to withdraw from vault\n * @param _amount The amount to withdraw from vault\n */\n function _withdraw(address account, uint256 _amount) internal {\n UserInfo storage user = userInfo[account];\n require(user.amount >= _amount, \"withdraw: not good\");\n\n updateVault();\n updateAndPayOutPending(account); // Update balances of account this is not withdrawal but claiming XVS farmed\n\n if (_amount > 0) {\n user.amount = user.amount.sub(_amount);\n vai.safeTransfer(address(account), _amount);\n }\n user.rewardDebt = user.amount.mul(accXVSPerShare).div(1e18);\n\n emit Withdraw(account, _amount);\n }\n\n /**\n * @notice View function to see pending XVS on frontend\n * @param _user The user to see pending XVS\n * @return Amount of XVS the user can claim\n */\n function pendingXVS(address _user) public view returns (uint256) {\n UserInfo storage user = userInfo[_user];\n\n return user.amount.mul(accXVSPerShare).div(1e18).sub(user.rewardDebt);\n }\n\n /**\n * @notice Update and pay out pending XVS to user\n * @param account The user to pay out\n */\n function updateAndPayOutPending(address account) internal {\n uint256 pending = pendingXVS(account);\n\n if (pending > 0) {\n safeXVSTransfer(account, pending);\n }\n }\n\n /**\n * @notice Safe XVS transfer function, just in case if rounding error causes pool to not have enough XVS\n * @param _to The address that XVS to be transfered\n * @param _amount The amount that XVS to be transfered\n */\n function safeXVSTransfer(address _to, uint256 _amount) internal {\n uint256 xvsBal = xvs.balanceOf(address(this));\n\n if (_amount > xvsBal) {\n xvs.transfer(_to, xvsBal);\n xvsBalance = xvs.balanceOf(address(this));\n } else {\n xvs.transfer(_to, _amount);\n xvsBalance = xvs.balanceOf(address(this));\n }\n }\n\n /**\n * @notice Function that updates pending rewards\n */\n function updatePendingRewards() public isActive {\n uint256 newRewards = xvs.balanceOf(address(this)).sub(xvsBalance);\n\n if (newRewards > 0) {\n xvsBalance = xvs.balanceOf(address(this)); // If there is no change the balance didn't change\n pendingRewards = pendingRewards.add(newRewards);\n }\n }\n\n /**\n * @notice Update reward variables to be up-to-date\n */\n function updateVault() internal {\n updatePendingRewards();\n\n uint256 vaiBalance = vai.balanceOf(address(this));\n if (vaiBalance == 0) {\n // avoids division by 0 errors\n return;\n }\n\n accXVSPerShare = accXVSPerShare.add(pendingRewards.mul(1e18).div(vaiBalance));\n pendingRewards = 0;\n }\n\n /*** Admin Functions ***/\n\n function _become(VAIVaultProxy vaiVaultProxy) external {\n require(msg.sender == vaiVaultProxy.admin(), \"only proxy admin can change brains\");\n require(vaiVaultProxy._acceptImplementation() == 0, \"change not authorized\");\n }\n\n function setVenusInfo(address _xvs, address _vai) external onlyAdmin {\n require(_xvs != address(0) && _vai != address(0), \"addresses must not be zero\");\n require(address(xvs) == address(0) && address(vai) == address(0), \"addresses already set\");\n xvs = IBEP20(_xvs);\n vai = IBEP20(_vai);\n\n _notEntered = true;\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlAddress New address for the access control\n */\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\n _setAccessControlManager(newAccessControlAddress);\n }\n}\n" + }, + "contracts/VAIVault/VAIVaultErrorReporter.sol": { + "content": "pragma solidity ^0.5.16;\n\ncontract VAIVaultErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED\n }\n\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n" + }, + "contracts/VAIVault/VAIVaultProxy.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./VAIVaultStorage.sol\";\nimport \"./VAIVaultErrorReporter.sol\";\n\n/**\n * @title VAI Vault Proxy\n * @author Venus\n * @notice Proxy contract for the VAI Vault\n */\ncontract VAIVaultProxy is VAIVaultAdminStorage, VAIVaultErrorReporter {\n /**\n * @notice Emitted when pendingVAIVaultImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingVAIVaultImplementation is accepted, which means VAI Vault implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor() public {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation = pendingVAIVaultImplementation;\n\n pendingVAIVaultImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIVaultImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new implementation of VAI Vault. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public returns (uint) {\n // Check caller is pendingImplementation\n if (msg.sender != pendingVAIVaultImplementation) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldImplementation = vaiVaultImplementation;\n address oldPendingImplementation = pendingVAIVaultImplementation;\n\n vaiVaultImplementation = pendingVAIVaultImplementation;\n\n pendingVAIVaultImplementation = address(0);\n\n emit NewImplementation(oldImplementation, vaiVaultImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIVaultImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\n // Check caller = admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n }\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n function() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = vaiVaultImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/VAIVault/VAIVaultStorage.sol": { + "content": "pragma solidity ^0.5.16;\nimport \"../Utils/SafeMath.sol\";\nimport \"../Utils/IBEP20.sol\";\n\ncontract VAIVaultAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of VAI Vault\n */\n address public vaiVaultImplementation;\n\n /**\n * @notice Pending brains of VAI Vault\n */\n address public pendingVAIVaultImplementation;\n}\n\ncontract VAIVaultStorage is VAIVaultAdminStorage {\n /// @notice The XVS TOKEN!\n IBEP20 public xvs;\n\n /// @notice The VAI TOKEN!\n IBEP20 public vai;\n\n /// @notice Guard variable for re-entrancy checks\n bool internal _notEntered;\n\n /// @notice XVS balance of vault\n uint256 public xvsBalance;\n\n /// @notice Accumulated XVS per share\n uint256 public accXVSPerShare;\n\n //// pending rewards awaiting anyone to update\n uint256 public pendingRewards;\n\n /// @notice Info of each user.\n struct UserInfo {\n uint256 amount;\n uint256 rewardDebt;\n }\n\n // Info of each user that stakes tokens.\n mapping(address => UserInfo) public userInfo;\n\n /// @notice pause indicator for Vault\n bool public vaultPaused;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/VRTVault/VRTVault.sol": { + "content": "pragma solidity 0.5.16;\n\nimport \"../Utils/SafeBEP20.sol\";\nimport \"../Utils/IBEP20.sol\";\nimport \"./VRTVaultStorage.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol\";\n\ninterface IVRTVaultProxy {\n function _acceptImplementation() external;\n\n function admin() external returns (address);\n}\n\ncontract VRTVault is VRTVaultStorage, AccessControlledV5 {\n using SafeMath for uint256;\n using SafeBEP20 for IBEP20;\n\n /// @notice The upper bound for lastAccruingBlock. Close to year 3,000, considering 3 seconds per block. Used to avoid a value absurdly high\n uint256 public constant MAX_LAST_ACCRUING_BLOCK = 9999999999;\n\n /// @notice Event emitted when vault is paused\n event VaultPaused(address indexed admin);\n\n /// @notice Event emitted when vault is resumed after pause\n event VaultResumed(address indexed admin);\n\n /// @notice Event emitted on VRT deposit\n event Deposit(address indexed user, uint256 amount);\n\n /// @notice Event emitted when accruedInterest and VRT PrincipalAmount is withrawn\n event Withdraw(\n address indexed user,\n uint256 withdrawnAmount,\n uint256 totalPrincipalAmount,\n uint256 accruedInterest\n );\n\n /// @notice Event emitted when Admin withdraw BEP20 token from contract\n event WithdrawToken(address indexed tokenAddress, address indexed receiver, uint256 amount);\n\n /// @notice Event emitted when accruedInterest is claimed\n event Claim(address indexed user, uint256 interestAmount);\n\n /// @notice Event emitted when lastAccruingBlock state variable changes\n event LastAccruingBlockChanged(uint256 oldLastAccruingBlock, uint256 newLastAccruingBlock);\n\n constructor() public {\n admin = msg.sender;\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin allowed\");\n _;\n }\n\n function initialize(address _vrtAddress, uint256 _interestRatePerBlock) public {\n require(msg.sender == admin, \"only admin may initialize the Vault\");\n require(_vrtAddress != address(0), \"vrtAddress cannot be Zero\");\n require(interestRatePerBlock == 0, \"Vault may only be initialized once\");\n\n // Set initial exchange rate\n interestRatePerBlock = _interestRatePerBlock;\n require(interestRatePerBlock > 0, \"interestRate Per Block must be greater than zero.\");\n\n // Set the VRT\n vrt = IBEP20(_vrtAddress);\n _notEntered = true;\n }\n\n modifier isInitialized() {\n require(interestRatePerBlock > 0, \"Vault is not initialized\");\n _;\n }\n\n modifier isActive() {\n require(!vaultPaused, \"Vault is paused\");\n _;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n modifier nonZeroAddress(address _address) {\n require(_address != address(0), \"Address cannot be Zero\");\n _;\n }\n\n modifier userHasPosition(address userAddress) {\n UserInfo storage user = userInfo[userAddress];\n require(user.userAddress != address(0), \"User does not have any position in the Vault.\");\n _;\n }\n\n /**\n * @notice Pause vault\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n require(!vaultPaused, \"Vault is already paused\");\n vaultPaused = true;\n emit VaultPaused(msg.sender);\n }\n\n /**\n * @notice Resume vault\n */\n function resume() external {\n _checkAccessAllowed(\"resume()\");\n require(vaultPaused, \"Vault is not paused\");\n vaultPaused = false;\n emit VaultResumed(msg.sender);\n }\n\n /**\n * @notice Deposit VRT to VRTVault for a fixed-interest-rate\n * @param depositAmount The amount to deposit to vault\n */\n function deposit(uint256 depositAmount) external nonReentrant isInitialized isActive {\n require(depositAmount > 0, \"Deposit amount must be non-zero\");\n\n address userAddress = msg.sender;\n UserInfo storage user = userInfo[userAddress];\n\n if (user.userAddress == address(0)) {\n user.userAddress = userAddress;\n user.totalPrincipalAmount = depositAmount;\n } else {\n // accrue Interest and transfer to the user\n uint256 accruedInterest = computeAccruedInterest(user.totalPrincipalAmount, user.accrualStartBlockNumber);\n\n user.totalPrincipalAmount = user.totalPrincipalAmount.add(depositAmount);\n\n if (accruedInterest > 0) {\n uint256 vrtBalance = vrt.balanceOf(address(this));\n require(\n vrtBalance >= accruedInterest,\n \"Failed to transfer accruedInterest, Insufficient VRT in Vault.\"\n );\n emit Claim(userAddress, accruedInterest);\n vrt.safeTransfer(user.userAddress, accruedInterest);\n }\n }\n\n uint256 currentBlock_ = getBlockNumber();\n if (lastAccruingBlock > currentBlock_) {\n user.accrualStartBlockNumber = currentBlock_;\n } else {\n user.accrualStartBlockNumber = lastAccruingBlock;\n }\n emit Deposit(userAddress, depositAmount);\n vrt.safeTransferFrom(userAddress, address(this), depositAmount);\n }\n\n /**\n * @notice get accruedInterest of the user's VRTDeposits in the Vault\n * @param userAddress Address of User in the the Vault\n * @return The interest accrued, in VRT\n */\n function getAccruedInterest(\n address userAddress\n ) public view nonZeroAddress(userAddress) isInitialized returns (uint256) {\n UserInfo storage user = userInfo[userAddress];\n if (user.accrualStartBlockNumber == 0) {\n return 0;\n }\n\n return computeAccruedInterest(user.totalPrincipalAmount, user.accrualStartBlockNumber);\n }\n\n /**\n * @notice get accruedInterest of the user's VRTDeposits in the Vault\n * @param totalPrincipalAmount of the User\n * @param accrualStartBlockNumber of the User\n * @return The interest accrued, in VRT\n */\n function computeAccruedInterest(\n uint256 totalPrincipalAmount,\n uint256 accrualStartBlockNumber\n ) internal view isInitialized returns (uint256) {\n uint256 blockNumber = getBlockNumber();\n uint256 _lastAccruingBlock = lastAccruingBlock;\n\n if (blockNumber > _lastAccruingBlock) {\n blockNumber = _lastAccruingBlock;\n }\n\n if (accrualStartBlockNumber == 0 || accrualStartBlockNumber >= blockNumber) {\n return 0;\n }\n\n // Number of blocks since deposit\n uint256 blockDelta = blockNumber.sub(accrualStartBlockNumber);\n uint256 accruedInterest = (totalPrincipalAmount.mul(interestRatePerBlock).mul(blockDelta)).div(1e18);\n return accruedInterest;\n }\n\n /**\n * @notice claim the accruedInterest of the user's VRTDeposits in the Vault\n */\n function claim() external nonReentrant isInitialized userHasPosition(msg.sender) isActive {\n _claim(msg.sender);\n }\n\n /**\n * @notice claim the accruedInterest of the user's VRTDeposits in the Vault\n * @param account The account for which to claim rewards\n */\n function claim(address account) external nonReentrant isInitialized userHasPosition(account) isActive {\n _claim(account);\n }\n\n /**\n * @notice Low level claim function\n * @param account The account for which to claim rewards\n */\n function _claim(address account) internal {\n uint256 accruedInterest = getAccruedInterest(account);\n if (accruedInterest > 0) {\n UserInfo storage user = userInfo[account];\n uint256 vrtBalance = vrt.balanceOf(address(this));\n require(vrtBalance >= accruedInterest, \"Failed to transfer VRT, Insufficient VRT in Vault.\");\n emit Claim(account, accruedInterest);\n uint256 currentBlock_ = getBlockNumber();\n if (lastAccruingBlock > currentBlock_) {\n user.accrualStartBlockNumber = currentBlock_;\n } else {\n user.accrualStartBlockNumber = lastAccruingBlock;\n }\n vrt.safeTransfer(user.userAddress, accruedInterest);\n }\n }\n\n /**\n * @notice withdraw accruedInterest and totalPrincipalAmount of the user's VRTDeposit in the Vault\n */\n function withdraw() external nonReentrant isInitialized userHasPosition(msg.sender) isActive {\n address userAddress = msg.sender;\n uint256 accruedInterest = getAccruedInterest(userAddress);\n\n UserInfo storage user = userInfo[userAddress];\n\n uint256 totalPrincipalAmount = user.totalPrincipalAmount;\n uint256 vrtForWithdrawal = accruedInterest.add(totalPrincipalAmount);\n user.totalPrincipalAmount = 0;\n user.accrualStartBlockNumber = getBlockNumber();\n\n uint256 vrtBalance = vrt.balanceOf(address(this));\n require(vrtBalance >= vrtForWithdrawal, \"Failed to transfer VRT, Insufficient VRT in Vault.\");\n\n emit Withdraw(userAddress, vrtForWithdrawal, totalPrincipalAmount, accruedInterest);\n vrt.safeTransfer(user.userAddress, vrtForWithdrawal);\n }\n\n /**\n * @notice withdraw BEP20 tokens from the contract to a recipient address.\n * @param tokenAddress address of the BEP20 token\n * @param receiver recipient of the BEP20 token\n * @param amount tokenAmount\n */\n function withdrawBep20(\n address tokenAddress,\n address receiver,\n uint256 amount\n ) external isInitialized nonZeroAddress(tokenAddress) nonZeroAddress(receiver) {\n _checkAccessAllowed(\"withdrawBep20(address,address,uint256)\");\n require(amount > 0, \"amount is invalid\");\n IBEP20 token = IBEP20(tokenAddress);\n require(amount <= token.balanceOf(address(this)), \"Insufficient amount in Vault\");\n emit WithdrawToken(tokenAddress, receiver, amount);\n token.safeTransfer(receiver, amount);\n }\n\n function setLastAccruingBlock(uint256 _lastAccruingBlock) external {\n _checkAccessAllowed(\"setLastAccruingBlock(uint256)\");\n require(_lastAccruingBlock < MAX_LAST_ACCRUING_BLOCK, \"_lastAccruingBlock is absurdly high\");\n\n uint256 oldLastAccruingBlock = lastAccruingBlock;\n uint256 currentBlock = getBlockNumber();\n if (oldLastAccruingBlock != 0) {\n require(currentBlock < oldLastAccruingBlock, \"Cannot change at this point\");\n }\n if (oldLastAccruingBlock == 0 || _lastAccruingBlock < oldLastAccruingBlock) {\n // Must be in future\n require(currentBlock < _lastAccruingBlock, \"Invalid _lastAccruingBlock interest have been accumulated\");\n }\n lastAccruingBlock = _lastAccruingBlock;\n emit LastAccruingBlockChanged(oldLastAccruingBlock, _lastAccruingBlock);\n }\n\n function getBlockNumber() public view returns (uint256) {\n return block.number;\n }\n\n /*** Admin Functions ***/\n\n function _become(IVRTVaultProxy vrtVaultProxy) external {\n require(msg.sender == vrtVaultProxy.admin(), \"only proxy admin can change brains\");\n vrtVaultProxy._acceptImplementation();\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlAddress New address for the access control\n */\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\n _setAccessControlManager(newAccessControlAddress);\n }\n}\n" + }, + "contracts/VRTVault/VRTVaultProxy.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./VRTVaultStorage.sol\";\n\ncontract VRTVaultProxy is VRTVaultAdminStorage {\n /**\n * @notice Emitted when pendingImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingImplementation is accepted, which means VRT Vault implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor(address implementation_, address vrtAddress_, uint256 interestRatePerBlock_) public {\n // Creator of the contract is admin during initialization\n admin = msg.sender;\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_);\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(\n implementation_,\n abi.encodeWithSignature(\"initialize(address,uint256)\", vrtAddress_, interestRatePerBlock_)\n );\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n */\n function _setImplementation(address implementation_) public {\n require(msg.sender == admin, \"VRTVaultProxy::_setImplementation: admin only\");\n require(implementation_ != address(0), \"VRTVaultProxy::_setImplementation: invalid implementation address\");\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize)\n }\n }\n return returnData;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public {\n require(msg.sender == admin, \"Only admin can set Pending Implementation\");\n\n address oldPendingImplementation = pendingImplementation;\n\n pendingImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingImplementation);\n }\n\n /**\n * @notice Accepts new implementation of VRT Vault. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n */\n function _acceptImplementation() public {\n // Check caller is pendingImplementation\n require(\n msg.sender == pendingImplementation,\n \"only address marked as pendingImplementation can accept Implementation\"\n );\n\n // Save current values for inclusion in log\n address oldImplementation = implementation;\n address oldPendingImplementation = pendingImplementation;\n\n implementation = pendingImplementation;\n\n pendingImplementation = address(0);\n\n emit NewImplementation(oldImplementation, implementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingImplementation);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n */\n function _setPendingAdmin(address newPendingAdmin) public {\n // Check caller = admin\n require(msg.sender == admin, \"only admin can set pending admin\");\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @dev return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public {\n // Check caller is pendingAdmin\n require(msg.sender == pendingAdmin, \"only address marked as pendingAdmin can accept as Admin\");\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n function() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/VRTVault/VRTVaultStorage.sol": { + "content": "pragma solidity ^0.5.16;\nimport \"../Utils/SafeMath.sol\";\nimport \"../Utils/IBEP20.sol\";\n\ncontract VRTVaultAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of VRT Vault\n */\n address public implementation;\n\n /**\n * @notice Pending brains of VAI Vault\n */\n address public pendingImplementation;\n}\n\ncontract VRTVaultStorage is VRTVaultAdminStorage {\n /// @notice Guard variable for re-entrancy checks\n bool public _notEntered;\n\n /// @notice pause indicator for Vault\n bool public vaultPaused;\n\n /// @notice The VRT TOKEN!\n IBEP20 public vrt;\n\n /// @notice interestRate for accrual - per Block\n uint256 public interestRatePerBlock;\n\n /// @notice Info of each user.\n struct UserInfo {\n address userAddress;\n uint256 accrualStartBlockNumber;\n uint256 totalPrincipalAmount;\n uint256 lastWithdrawnBlockNumber;\n }\n\n // Info of each user that stakes tokens.\n mapping(address => UserInfo) public userInfo;\n\n /// @notice block number after which no interest will be accrued\n uint256 public lastAccruingBlock;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "contracts/XVSVault/XVSStore.sol": { + "content": "pragma solidity 0.5.16;\nimport \"../Utils/SafeBEP20.sol\";\nimport \"../Utils/IBEP20.sol\";\n\n/**\n * @title XVS Store\n * @author Venus\n * @notice XVS Store responsible for distributing XVS rewards\n */\ncontract XVSStore {\n using SafeMath for uint256;\n using SafeBEP20 for IBEP20;\n\n /// @notice The Admin Address\n address public admin;\n\n /// @notice The pending admin address\n address public pendingAdmin;\n\n /// @notice The Owner Address\n address public owner;\n\n /// @notice The reward tokens\n mapping(address => bool) public rewardTokens;\n\n /// @notice Emitted when pendingAdmin is changed\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /// @notice Event emitted when admin changed\n event AdminTransferred(address indexed oldAdmin, address indexed newAdmin);\n\n /// @notice Event emitted when owner changed\n event OwnerTransferred(address indexed oldOwner, address indexed newOwner);\n\n constructor() public {\n admin = msg.sender;\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin can\");\n _;\n }\n\n modifier onlyOwner() {\n require(msg.sender == owner, \"only owner can\");\n _;\n }\n\n /**\n * @notice Safely transfer rewards. Only active reward tokens can be sent using this function.\n * Only callable by owner\n * @dev Safe reward token transfer function, just in case if rounding error causes pool to not have enough tokens.\n * @param token Reward token to transfer\n * @param _to Destination address of the reward\n * @param _amount Amount to transfer\n */\n function safeRewardTransfer(address token, address _to, uint256 _amount) external onlyOwner {\n require(rewardTokens[token] == true, \"only reward token can\");\n\n if (address(token) != address(0)) {\n uint256 tokenBalance = IBEP20(token).balanceOf(address(this));\n if (_amount > tokenBalance) {\n IBEP20(token).safeTransfer(_to, tokenBalance);\n } else {\n IBEP20(token).safeTransfer(_to, _amount);\n }\n }\n }\n\n /**\n * @notice Allows the admin to propose a new admin\n * Only callable admin\n * @param _admin Propose an account as admin of the XVS store\n */\n function setPendingAdmin(address _admin) external onlyAdmin {\n address oldPendingAdmin = pendingAdmin;\n pendingAdmin = _admin;\n emit NewPendingAdmin(oldPendingAdmin, _admin);\n }\n\n /**\n * @notice Allows an account that is pending as admin to accept the role\n * nly calllable by the pending admin\n */\n function acceptAdmin() external {\n require(msg.sender == pendingAdmin, \"only pending admin\");\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n admin = pendingAdmin;\n pendingAdmin = address(0);\n\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n emit AdminTransferred(oldAdmin, admin);\n }\n\n /**\n * @notice Set the contract owner\n * @param _owner The address of the owner to set\n * Only callable admin\n */\n function setNewOwner(address _owner) external onlyAdmin {\n require(_owner != address(0), \"new owner is the zero address\");\n address oldOwner = owner;\n owner = _owner;\n emit OwnerTransferred(oldOwner, _owner);\n }\n\n /**\n * @notice Set or disable a reward token\n * @param _tokenAddress The address of a token to set as active or inactive\n * @param status Set whether a reward token is active or not\n */\n function setRewardToken(address _tokenAddress, bool status) external {\n require(msg.sender == admin || msg.sender == owner, \"only admin or owner can\");\n rewardTokens[_tokenAddress] = status;\n }\n\n /**\n * @notice Security function to allow the owner of the contract to withdraw from the contract\n * @param _tokenAddress Reward token address to withdraw\n * @param _amount Amount of token to withdraw\n */\n function emergencyRewardWithdraw(address _tokenAddress, uint256 _amount) external onlyOwner {\n IBEP20(_tokenAddress).safeTransfer(address(msg.sender), _amount);\n }\n}\n" + }, + "contracts/XVSVault/XVSVault.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.5.16;\npragma experimental ABIEncoderV2;\n\nimport \"../Utils/ECDSA.sol\";\nimport \"../Utils/SafeBEP20.sol\";\nimport \"../Utils/IBEP20.sol\";\nimport \"./XVSVaultStorage.sol\";\nimport \"./XVSVaultErrorReporter.sol\";\nimport \"../Tokens/Prime/IPrime.sol\";\nimport \"../Utils/SafeCast.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV5.sol\";\nimport { XVSStore } from \"./XVSStore.sol\";\nimport { XVSVaultProxy } from \"./XVSVaultProxy.sol\";\n\n/**\n * @title XVS Vault\n * @author Venus\n * @notice The XVS Vault allows XVS holders to lock their XVS to recieve voting rights in Venus governance and are rewarded with XVS.\n */\ncontract XVSVault is XVSVaultStorage, ECDSA, AccessControlledV5 {\n using SafeMath for uint256;\n using SafeCast for uint256;\n using SafeBEP20 for IBEP20;\n\n /// @notice The upper bound for the lock period in a pool, 10 years\n uint256 public constant MAX_LOCK_PERIOD = 60 * 60 * 24 * 365 * 10;\n\n /// @notice Event emitted when deposit\n event Deposit(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\n\n /// @notice Event emitted when execute withrawal\n event ExecutedWithdrawal(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\n\n /// @notice Event emitted when request withrawal\n event RequestedWithdrawal(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\n\n /// @notice An event thats emitted when an account changes its delegate\n event DelegateChangedV2(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /// @notice An event thats emitted when a delegate account's vote balance changes\n event DelegateVotesChangedV2(address indexed delegate, uint previousBalance, uint newBalance);\n\n /// @notice An event emitted when the reward store address is updated\n event StoreUpdated(address oldXvs, address oldStore, address newXvs, address newStore);\n\n /// @notice An event emitted when the withdrawal locking period is updated for a pool\n event WithdrawalLockingPeriodUpdated(address indexed rewardToken, uint indexed pid, uint oldPeriod, uint newPeriod);\n\n /// @notice An event emitted when the reward amount per block is modified for a pool\n event RewardAmountUpdated(address indexed rewardToken, uint oldReward, uint newReward);\n\n /// @notice An event emitted when a new pool is added\n event PoolAdded(\n address indexed rewardToken,\n uint indexed pid,\n address indexed token,\n uint allocPoints,\n uint rewardPerBlock,\n uint lockPeriod\n );\n\n /// @notice An event emitted when a pool allocation points are updated\n event PoolUpdated(address indexed rewardToken, uint indexed pid, uint oldAllocPoints, uint newAllocPoints);\n\n /// @notice Event emitted when reward claimed\n event Claim(address indexed user, address indexed rewardToken, uint256 indexed pid, uint256 amount);\n\n /// @notice Event emitted when vault is paused\n event VaultPaused(address indexed admin);\n\n /// @notice Event emitted when vault is resumed after pause\n event VaultResumed(address indexed admin);\n\n /// @notice Event emitted when protocol logs a debt to a user due to insufficient funds for pending reward distribution\n event VaultDebtUpdated(\n address indexed rewardToken,\n address indexed userAddress,\n uint256 oldOwedAmount,\n uint256 newOwedAmount\n );\n\n /// @notice Emitted when prime token contract address is changed\n event NewPrimeToken(\n IPrime indexed oldPrimeToken,\n IPrime indexed newPrimeToken,\n address oldPrimeRewardToken,\n address newPrimeRewardToken,\n uint256 oldPrimePoolId,\n uint256 newPrimePoolId\n );\n\n constructor() public {\n admin = msg.sender;\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin can\");\n _;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n /**\n * @dev Prevents functions to execute when vault is paused.\n */\n modifier isActive() {\n require(!vaultPaused, \"Vault is paused\");\n _;\n }\n\n /**\n * @notice Pauses vault\n */\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n require(!vaultPaused, \"Vault is already paused\");\n vaultPaused = true;\n emit VaultPaused(msg.sender);\n }\n\n /**\n * @notice Resume vault\n */\n function resume() external {\n _checkAccessAllowed(\"resume()\");\n require(vaultPaused, \"Vault is not paused\");\n vaultPaused = false;\n emit VaultResumed(msg.sender);\n }\n\n /**\n * @notice Returns the number of pools with the specified reward token\n * @param rewardToken Reward token address\n * @return Number of pools that distribute the specified token as a reward\n */\n function poolLength(address rewardToken) external view returns (uint256) {\n return poolInfos[rewardToken].length;\n }\n\n /**\n * @notice Add a new token pool\n * @dev This vault DOES NOT support deflationary tokens — it expects that\n * the amount of transferred tokens would equal the actually deposited\n * amount. In practice this means that this vault DOES NOT support USDT\n * and similar tokens (that do not provide these guarantees).\n * @param _rewardToken Reward token address\n * @param _allocPoint Number of allocation points assigned to this pool\n * @param _token Staked token\n * @param _rewardPerBlock Initial reward per block, in terms of _rewardToken\n * @param _lockPeriod A period between withdrawal request and a moment when it's executable\n */\n function add(\n address _rewardToken,\n uint256 _allocPoint,\n IBEP20 _token,\n uint256 _rewardPerBlock,\n uint256 _lockPeriod\n ) external {\n _checkAccessAllowed(\"add(address,uint256,address,uint256,uint256)\");\n _ensureNonzeroAddress(_rewardToken);\n _ensureNonzeroAddress(address(_token));\n require(address(xvsStore) != address(0), \"Store contract address is empty\");\n require(_allocPoint > 0, \"Alloc points must not be zero\");\n\n massUpdatePools(_rewardToken);\n\n PoolInfo[] storage poolInfo = poolInfos[_rewardToken];\n\n uint256 length = poolInfo.length;\n for (uint256 pid = 0; pid < length; ++pid) {\n require(poolInfo[pid].token != _token, \"Pool already added\");\n }\n\n // We use balanceOf to get the supply amount, so shouldn't be possible to\n // configure pools with different reward token but the same staked token\n require(!isStakedToken[address(_token)], \"Token exists in other pool\");\n\n totalAllocPoints[_rewardToken] = totalAllocPoints[_rewardToken].add(_allocPoint);\n\n rewardTokenAmountsPerBlock[_rewardToken] = _rewardPerBlock;\n\n poolInfo.push(\n PoolInfo({\n token: _token,\n allocPoint: _allocPoint,\n lastRewardBlock: block.number,\n accRewardPerShare: 0,\n lockPeriod: _lockPeriod\n })\n );\n isStakedToken[address(_token)] = true;\n\n XVSStore(xvsStore).setRewardToken(_rewardToken, true);\n\n emit PoolAdded(_rewardToken, poolInfo.length - 1, address(_token), _allocPoint, _rewardPerBlock, _lockPeriod);\n }\n\n /**\n * @notice Update the given pool's reward allocation point\n * @param _rewardToken Reward token address\n * @param _pid Pool index\n * @param _allocPoint Number of allocation points assigned to this pool\n */\n function set(address _rewardToken, uint256 _pid, uint256 _allocPoint) external {\n _checkAccessAllowed(\"set(address,uint256,uint256)\");\n _ensureValidPool(_rewardToken, _pid);\n\n massUpdatePools(_rewardToken);\n\n PoolInfo[] storage poolInfo = poolInfos[_rewardToken];\n uint256 newTotalAllocPoints = totalAllocPoints[_rewardToken].sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n require(newTotalAllocPoints > 0, \"Alloc points per reward token must not be zero\");\n\n uint256 oldAllocPoints = poolInfo[_pid].allocPoint;\n poolInfo[_pid].allocPoint = _allocPoint;\n totalAllocPoints[_rewardToken] = newTotalAllocPoints;\n\n emit PoolUpdated(_rewardToken, _pid, oldAllocPoints, _allocPoint);\n }\n\n /**\n * @notice Update the given reward token's amount per block\n * @param _rewardToken Reward token address\n * @param _rewardAmount Number of allocation points assigned to this pool\n */\n function setRewardAmountPerBlock(address _rewardToken, uint256 _rewardAmount) external {\n _checkAccessAllowed(\"setRewardAmountPerBlock(address,uint256)\");\n require(XVSStore(xvsStore).rewardTokens(_rewardToken), \"Invalid reward token\");\n massUpdatePools(_rewardToken);\n uint256 oldReward = rewardTokenAmountsPerBlock[_rewardToken];\n rewardTokenAmountsPerBlock[_rewardToken] = _rewardAmount;\n\n emit RewardAmountUpdated(_rewardToken, oldReward, _rewardAmount);\n }\n\n /**\n * @notice Update the lock period after which a requested withdrawal can be executed\n * @param _rewardToken Reward token address\n * @param _pid Pool index\n * @param _newPeriod New lock period\n */\n function setWithdrawalLockingPeriod(address _rewardToken, uint256 _pid, uint256 _newPeriod) external {\n _checkAccessAllowed(\"setWithdrawalLockingPeriod(address,uint256,uint256)\");\n _ensureValidPool(_rewardToken, _pid);\n require(_newPeriod > 0 && _newPeriod < MAX_LOCK_PERIOD, \"Invalid new locking period\");\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n uint256 oldPeriod = pool.lockPeriod;\n pool.lockPeriod = _newPeriod;\n\n emit WithdrawalLockingPeriodUpdated(_rewardToken, _pid, oldPeriod, _newPeriod);\n }\n\n /**\n * @notice Deposit XVSVault for XVS allocation\n * @param _rewardToken The Reward Token Address\n * @param _pid The Pool Index\n * @param _amount The amount to deposit to vault\n */\n function deposit(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant isActive {\n _ensureValidPool(_rewardToken, _pid);\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\n _updatePool(_rewardToken, _pid);\n require(pendingWithdrawalsBeforeUpgrade(_rewardToken, _pid, msg.sender) == 0, \"execute pending withdrawal\");\n\n if (user.amount > 0) {\n uint256 pending = _computeReward(user, pool);\n if (pending > 0) {\n _transferReward(_rewardToken, msg.sender, pending);\n emit Claim(msg.sender, _rewardToken, _pid, pending);\n }\n }\n pool.token.safeTransferFrom(msg.sender, address(this), _amount);\n user.amount = user.amount.add(_amount);\n user.rewardDebt = _cumulativeReward(user, pool);\n\n // Update Delegate Amount\n if (address(pool.token) == xvsAddress) {\n _moveDelegates(address(0), delegates[msg.sender], safe96(_amount, \"XVSVault::deposit: votes overflow\"));\n }\n\n if (primeRewardToken == _rewardToken && _pid == primePoolId) {\n primeToken.xvsUpdated(msg.sender);\n }\n\n emit Deposit(msg.sender, _rewardToken, _pid, _amount);\n }\n\n /**\n * @notice Claim rewards for pool\n * @param _account The account for which to claim rewards\n * @param _rewardToken The Reward Token Address\n * @param _pid The Pool Index\n */\n function claim(address _account, address _rewardToken, uint256 _pid) external nonReentrant isActive {\n _ensureValidPool(_rewardToken, _pid);\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n UserInfo storage user = userInfos[_rewardToken][_pid][_account];\n _updatePool(_rewardToken, _pid);\n require(pendingWithdrawalsBeforeUpgrade(_rewardToken, _pid, _account) == 0, \"execute pending withdrawal\");\n\n if (user.amount > 0) {\n uint256 pending = _computeReward(user, pool);\n\n if (pending > 0) {\n user.rewardDebt = _cumulativeReward(user, pool);\n\n _transferReward(_rewardToken, _account, pending);\n emit Claim(_account, _rewardToken, _pid, pending);\n }\n }\n }\n\n /**\n * @notice Pushes withdrawal request to the requests array and updates\n * the pending withdrawals amount. The requests are always sorted\n * by unlock time (descending) so that the earliest to execute requests\n * are always at the end of the array.\n * @param _user The user struct storage pointer\n * @param _requests The user's requests array storage pointer\n * @param _amount The amount being requested\n */\n function pushWithdrawalRequest(\n UserInfo storage _user,\n WithdrawalRequest[] storage _requests,\n uint _amount,\n uint _lockedUntil\n ) internal {\n uint i = _requests.length;\n _requests.push(WithdrawalRequest(0, 0, 1));\n // Keep it sorted so that the first to get unlocked request is always at the end\n for (; i > 0 && _requests[i - 1].lockedUntil <= _lockedUntil; --i) {\n _requests[i] = _requests[i - 1];\n }\n _requests[i] = WithdrawalRequest(_amount, _lockedUntil.toUint128(), 1);\n _user.pendingWithdrawals = _user.pendingWithdrawals.add(_amount);\n }\n\n /**\n * @notice Pops the requests with unlock time < now from the requests\n * array and deducts the computed amount from the user's pending\n * withdrawals counter. Assumes that the requests array is sorted\n * by unclock time (descending).\n * @dev This function **removes** the eligible requests from the requests\n * array. If this function is called, the withdrawal should actually\n * happen (or the transaction should be reverted).\n * @param _user The user struct storage pointer\n * @param _requests The user's requests array storage pointer\n * @return beforeUpgradeWithdrawalAmount The amount eligible for withdrawal before upgrade (this amount should be\n * sent to the user, otherwise the state would be inconsistent).\n * @return afterUpgradeWithdrawalAmount The amount eligible for withdrawal after upgrade (this amount should be\n * sent to the user, otherwise the state would be inconsistent).\n */\n function popEligibleWithdrawalRequests(\n UserInfo storage _user,\n WithdrawalRequest[] storage _requests\n ) internal returns (uint beforeUpgradeWithdrawalAmount, uint afterUpgradeWithdrawalAmount) {\n // Since the requests are sorted by their unlock time, we can just\n // pop them from the array and stop at the first not-yet-eligible one\n for (uint i = _requests.length; i > 0 && isUnlocked(_requests[i - 1]); --i) {\n if (_requests[i - 1].afterUpgrade == 1) {\n afterUpgradeWithdrawalAmount = afterUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\n } else {\n beforeUpgradeWithdrawalAmount = beforeUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\n }\n\n _requests.pop();\n }\n _user.pendingWithdrawals = _user.pendingWithdrawals.sub(\n afterUpgradeWithdrawalAmount.add(beforeUpgradeWithdrawalAmount)\n );\n return (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount);\n }\n\n /**\n * @notice Checks if the request is eligible for withdrawal.\n * @param _request The request struct storage pointer\n * @return True if the request is eligible for withdrawal, false otherwise\n */\n function isUnlocked(WithdrawalRequest storage _request) private view returns (bool) {\n return _request.lockedUntil <= block.timestamp;\n }\n\n /**\n * @notice Execute withdrawal to XVSVault for XVS allocation\n * @param _rewardToken The Reward Token Address\n * @param _pid The Pool Index\n */\n function executeWithdrawal(address _rewardToken, uint256 _pid) external nonReentrant isActive {\n _ensureValidPool(_rewardToken, _pid);\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];\n\n uint256 beforeUpgradeWithdrawalAmount;\n uint256 afterUpgradeWithdrawalAmount;\n\n (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount) = popEligibleWithdrawalRequests(user, requests);\n require(beforeUpgradeWithdrawalAmount > 0 || afterUpgradeWithdrawalAmount > 0, \"nothing to withdraw\");\n\n // Having both old-style and new-style requests is not allowed and shouldn't be possible\n require(beforeUpgradeWithdrawalAmount == 0 || afterUpgradeWithdrawalAmount == 0, \"inconsistent state\");\n\n if (beforeUpgradeWithdrawalAmount > 0) {\n _updatePool(_rewardToken, _pid);\n uint256 pending = user.amount.mul(pool.accRewardPerShare).div(1e12).sub(user.rewardDebt);\n XVSStore(xvsStore).safeRewardTransfer(_rewardToken, msg.sender, pending);\n user.amount = user.amount.sub(beforeUpgradeWithdrawalAmount);\n user.rewardDebt = user.amount.mul(pool.accRewardPerShare).div(1e12);\n pool.token.safeTransfer(address(msg.sender), beforeUpgradeWithdrawalAmount);\n } else {\n user.amount = user.amount.sub(afterUpgradeWithdrawalAmount);\n totalPendingWithdrawals[_rewardToken][_pid] = totalPendingWithdrawals[_rewardToken][_pid].sub(\n afterUpgradeWithdrawalAmount\n );\n pool.token.safeTransfer(address(msg.sender), afterUpgradeWithdrawalAmount);\n }\n\n emit ExecutedWithdrawal(\n msg.sender,\n _rewardToken,\n _pid,\n beforeUpgradeWithdrawalAmount.add(afterUpgradeWithdrawalAmount)\n );\n }\n\n /**\n * @notice Returns before and after upgrade pending withdrawal amount\n * @param _requests The user's requests array storage pointer\n * @return beforeUpgradeWithdrawalAmount The amount eligible for withdrawal before upgrade\n * @return afterUpgradeWithdrawalAmount The amount eligible for withdrawal after upgrade\n */\n function getRequestedWithdrawalAmount(\n WithdrawalRequest[] storage _requests\n ) internal view returns (uint beforeUpgradeWithdrawalAmount, uint afterUpgradeWithdrawalAmount) {\n for (uint i = _requests.length; i > 0; --i) {\n if (_requests[i - 1].afterUpgrade == 1) {\n afterUpgradeWithdrawalAmount = afterUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\n } else {\n beforeUpgradeWithdrawalAmount = beforeUpgradeWithdrawalAmount.add(_requests[i - 1].amount);\n }\n }\n return (beforeUpgradeWithdrawalAmount, afterUpgradeWithdrawalAmount);\n }\n\n /**\n * @notice Request withdrawal to XVSVault for XVS allocation\n * @param _rewardToken The Reward Token Address\n * @param _pid The Pool Index\n * @param _amount The amount to withdraw from the vault\n */\n function requestWithdrawal(address _rewardToken, uint256 _pid, uint256 _amount) external nonReentrant isActive {\n _ensureValidPool(_rewardToken, _pid);\n require(_amount > 0, \"requested amount cannot be zero\");\n UserInfo storage user = userInfos[_rewardToken][_pid][msg.sender];\n require(user.amount >= user.pendingWithdrawals.add(_amount), \"requested amount is invalid\");\n\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][msg.sender];\n\n uint beforeUpgradeWithdrawalAmount;\n\n (beforeUpgradeWithdrawalAmount, ) = getRequestedWithdrawalAmount(requests);\n require(beforeUpgradeWithdrawalAmount == 0, \"execute pending withdrawal\");\n\n _updatePool(_rewardToken, _pid);\n uint256 pending = _computeReward(user, pool);\n _transferReward(_rewardToken, msg.sender, pending);\n\n uint lockedUntil = pool.lockPeriod.add(block.timestamp);\n\n pushWithdrawalRequest(user, requests, _amount, lockedUntil);\n totalPendingWithdrawals[_rewardToken][_pid] = totalPendingWithdrawals[_rewardToken][_pid].add(_amount);\n user.rewardDebt = _cumulativeReward(user, pool);\n\n // Update Delegate Amount\n if (address(pool.token) == xvsAddress) {\n _moveDelegates(\n delegates[msg.sender],\n address(0),\n safe96(_amount, \"XVSVault::requestWithdrawal: votes overflow\")\n );\n }\n\n if (primeRewardToken == _rewardToken && _pid == primePoolId) {\n primeToken.xvsUpdated(msg.sender);\n }\n\n emit Claim(msg.sender, _rewardToken, _pid, pending);\n emit RequestedWithdrawal(msg.sender, _rewardToken, _pid, _amount);\n }\n\n /**\n * @notice Get unlocked withdrawal amount\n * @param _rewardToken The Reward Token Address\n * @param _pid The Pool Index\n * @param _user The User Address\n * @return withdrawalAmount Amount that the user can withdraw\n */\n function getEligibleWithdrawalAmount(\n address _rewardToken,\n uint256 _pid,\n address _user\n ) external view returns (uint withdrawalAmount) {\n _ensureValidPool(_rewardToken, _pid);\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\n // Since the requests are sorted by their unlock time, we can take\n // the entries from the end of the array and stop at the first\n // not-yet-eligible one\n for (uint i = requests.length; i > 0 && isUnlocked(requests[i - 1]); --i) {\n withdrawalAmount = withdrawalAmount.add(requests[i - 1].amount);\n }\n return withdrawalAmount;\n }\n\n /**\n * @notice Get requested amount\n * @param _rewardToken The Reward Token Address\n * @param _pid The Pool Index\n * @param _user The User Address\n * @return Total amount of requested but not yet executed withdrawals (including both executable and locked ones)\n */\n function getRequestedAmount(address _rewardToken, uint256 _pid, address _user) external view returns (uint256) {\n _ensureValidPool(_rewardToken, _pid);\n UserInfo storage user = userInfos[_rewardToken][_pid][_user];\n return user.pendingWithdrawals;\n }\n\n /**\n * @notice Returns the array of withdrawal requests that have not been executed yet\n * @param _rewardToken The Reward Token Address\n * @param _pid The Pool Index\n * @param _user The User Address\n * @return An array of withdrawal requests\n */\n function getWithdrawalRequests(\n address _rewardToken,\n uint256 _pid,\n address _user\n ) external view returns (WithdrawalRequest[] memory) {\n _ensureValidPool(_rewardToken, _pid);\n return withdrawalRequests[_rewardToken][_pid][_user];\n }\n\n /**\n * @notice View function to see pending XVSs on frontend\n * @param _rewardToken Reward token address\n * @param _pid Pool index\n * @param _user User address\n * @return Reward the user is eligible for in this pool, in terms of _rewardToken\n */\n function pendingReward(address _rewardToken, uint256 _pid, address _user) external view returns (uint256) {\n _ensureValidPool(_rewardToken, _pid);\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n UserInfo storage user = userInfos[_rewardToken][_pid][_user];\n uint256 accRewardPerShare = pool.accRewardPerShare;\n uint256 supply = pool.token.balanceOf(address(this)).sub(totalPendingWithdrawals[_rewardToken][_pid]);\n uint256 curBlockNumber = block.number;\n uint256 rewardTokenPerBlock = rewardTokenAmountsPerBlock[_rewardToken];\n if (curBlockNumber > pool.lastRewardBlock && supply != 0) {\n uint256 multiplier = curBlockNumber.sub(pool.lastRewardBlock);\n uint256 reward = multiplier.mul(rewardTokenPerBlock).mul(pool.allocPoint).div(\n totalAllocPoints[_rewardToken]\n );\n accRewardPerShare = accRewardPerShare.add(reward.mul(1e12).div(supply));\n }\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\n (, uint256 afterUpgradeWithdrawalAmount) = getRequestedWithdrawalAmount(requests);\n return user.amount.sub(afterUpgradeWithdrawalAmount).mul(accRewardPerShare).div(1e12).sub(user.rewardDebt);\n }\n\n // Update reward variables for all pools. Be careful of gas spending!\n function massUpdatePools(address _rewardToken) internal {\n uint256 length = poolInfos[_rewardToken].length;\n for (uint256 pid = 0; pid < length; ++pid) {\n _updatePool(_rewardToken, pid);\n }\n }\n\n /**\n * @notice Update reward variables of the given pool to be up-to-date\n * @param _rewardToken Reward token address\n * @param _pid Pool index\n */\n function updatePool(address _rewardToken, uint256 _pid) external isActive {\n _ensureValidPool(_rewardToken, _pid);\n _updatePool(_rewardToken, _pid);\n }\n\n // Update reward variables of the given pool to be up-to-date.\n function _updatePool(address _rewardToken, uint256 _pid) internal {\n PoolInfo storage pool = poolInfos[_rewardToken][_pid];\n if (block.number <= pool.lastRewardBlock) {\n return;\n }\n uint256 supply = pool.token.balanceOf(address(this));\n supply = supply.sub(totalPendingWithdrawals[_rewardToken][_pid]);\n if (supply == 0) {\n pool.lastRewardBlock = block.number;\n return;\n }\n uint256 curBlockNumber = block.number;\n uint256 multiplier = curBlockNumber.sub(pool.lastRewardBlock);\n uint256 reward = multiplier.mul(rewardTokenAmountsPerBlock[_rewardToken]).mul(pool.allocPoint).div(\n totalAllocPoints[_rewardToken]\n );\n pool.accRewardPerShare = pool.accRewardPerShare.add(reward.mul(1e12).div(supply));\n pool.lastRewardBlock = block.number;\n }\n\n function _ensureValidPool(address rewardToken, uint256 pid) internal view {\n require(pid < poolInfos[rewardToken].length, \"vault: pool exists?\");\n }\n\n /**\n * @notice Get user info with reward token address and pid\n * @param _rewardToken Reward token address\n * @param _pid Pool index\n * @param _user User address\n * @return amount Deposited amount\n * @return rewardDebt Reward debt (technical value used to track past payouts)\n * @return pendingWithdrawals Requested but not yet executed withdrawals\n */\n function getUserInfo(\n address _rewardToken,\n uint256 _pid,\n address _user\n ) external view returns (uint256 amount, uint256 rewardDebt, uint256 pendingWithdrawals) {\n _ensureValidPool(_rewardToken, _pid);\n UserInfo storage user = userInfos[_rewardToken][_pid][_user];\n amount = user.amount;\n rewardDebt = user.rewardDebt;\n pendingWithdrawals = user.pendingWithdrawals;\n }\n\n /**\n * @notice Gets the total pending withdrawal amount of a user before upgrade\n * @param _rewardToken The Reward Token Address\n * @param _pid The Pool Index\n * @param _user The address of the user\n * @return beforeUpgradeWithdrawalAmount Total pending withdrawal amount in requests made before the vault upgrade\n */\n function pendingWithdrawalsBeforeUpgrade(\n address _rewardToken,\n uint256 _pid,\n address _user\n ) public view returns (uint256 beforeUpgradeWithdrawalAmount) {\n WithdrawalRequest[] storage requests = withdrawalRequests[_rewardToken][_pid][_user];\n (beforeUpgradeWithdrawalAmount, ) = getRequestedWithdrawalAmount(requests);\n return beforeUpgradeWithdrawalAmount;\n }\n\n /**\n * @notice Get the XVS stake balance of an account (excluding the pending withdrawals)\n * @param account The address of the account to check\n * @return The balance that user staked\n */\n function getStakeAmount(address account) internal view returns (uint96) {\n require(xvsAddress != address(0), \"XVSVault::getStakeAmount: xvs address is not set\");\n\n PoolInfo[] storage poolInfo = poolInfos[xvsAddress];\n\n uint256 length = poolInfo.length;\n for (uint256 pid = 0; pid < length; ++pid) {\n if (address(poolInfo[pid].token) == address(xvsAddress)) {\n UserInfo storage user = userInfos[xvsAddress][pid][account];\n return safe96(user.amount.sub(user.pendingWithdrawals), \"XVSVault::getStakeAmount: votes overflow\");\n }\n }\n return uint96(0);\n }\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) external isActive {\n return _delegate(msg.sender, delegatee);\n }\n\n /**\n * @notice Delegates votes from signatory to `delegatee`\n * @param delegatee The address to delegate votes to\n * @param nonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v The recovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\n function delegateBySig(\n address delegatee,\n uint nonce,\n uint expiry,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external isActive {\n bytes32 domainSeparator = keccak256(\n abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(\"XVSVault\")), getChainId(), address(this))\n );\n bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n address signatory = ECDSA.recover(digest, v, r, s);\n require(nonce == nonces[signatory]++, \"XVSVault::delegateBySig: invalid nonce\");\n require(block.timestamp <= expiry, \"XVSVault::delegateBySig: signature expired\");\n return _delegate(signatory, delegatee);\n }\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getCurrentVotes(address account) external view returns (uint96) {\n uint32 nCheckpoints = numCheckpoints[account];\n return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n }\n\n function _delegate(address delegator, address delegatee) internal {\n address currentDelegate = delegates[delegator];\n uint96 delegatorBalance = getStakeAmount(delegator);\n delegates[delegator] = delegatee;\n\n emit DelegateChangedV2(delegator, currentDelegate, delegatee);\n\n _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n }\n\n function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {\n if (srcRep != dstRep && amount > 0) {\n if (srcRep != address(0)) {\n uint32 srcRepNum = numCheckpoints[srcRep];\n uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\n uint96 srcRepNew = sub96(srcRepOld, amount, \"XVSVault::_moveVotes: vote amount underflows\");\n _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n }\n\n if (dstRep != address(0)) {\n uint32 dstRepNum = numCheckpoints[dstRep];\n uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\n uint96 dstRepNew = add96(dstRepOld, amount, \"XVSVault::_moveVotes: vote amount overflows\");\n _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n }\n }\n }\n\n function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\n uint32 blockNumber = safe32(block.number, \"XVSVault::_writeCheckpoint: block number exceeds 32 bits\");\n\n if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\n checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n } else {\n checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\n numCheckpoints[delegatee] = nCheckpoints + 1;\n }\n\n emit DelegateVotesChangedV2(delegatee, oldVotes, newVotes);\n }\n\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n require(n < 2 ** 32, errorMessage);\n return uint32(n);\n }\n\n function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\n require(n < 2 ** 96, errorMessage);\n return uint96(n);\n }\n\n function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n uint96 c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function getChainId() internal pure returns (uint) {\n uint256 chainId;\n assembly {\n chainId := chainid()\n }\n return chainId;\n }\n\n /**\n * @notice Determine the xvs stake balance for an account\n * @param account The address of the account to check\n * @param blockNumber The block number to get the vote balance at\n * @return The balance that user staked\n */\n function getPriorVotes(address account, uint256 blockNumber) external view returns (uint96) {\n require(blockNumber < block.number, \"XVSVault::getPriorVotes: not yet determined\");\n\n uint32 nCheckpoints = numCheckpoints[account];\n if (nCheckpoints == 0) {\n return 0;\n }\n\n // First check most recent balance\n if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\n return checkpoints[account][nCheckpoints - 1].votes;\n }\n\n // Next check implicit zero balance\n if (checkpoints[account][0].fromBlock > blockNumber) {\n return 0;\n }\n\n uint32 lower = 0;\n uint32 upper = nCheckpoints - 1;\n while (upper > lower) {\n uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n Checkpoint memory cp = checkpoints[account][center];\n if (cp.fromBlock == blockNumber) {\n return cp.votes;\n } else if (cp.fromBlock < blockNumber) {\n lower = center;\n } else {\n upper = center - 1;\n }\n }\n return checkpoints[account][lower].votes;\n }\n\n /*** Admin Functions ***/\n\n function _become(XVSVaultProxy xvsVaultProxy) external {\n require(msg.sender == xvsVaultProxy.admin(), \"only proxy admin can change brains\");\n require(xvsVaultProxy._acceptImplementation() == 0, \"change not authorized\");\n }\n\n function setXvsStore(address _xvs, address _xvsStore) external onlyAdmin {\n _ensureNonzeroAddress(_xvs);\n _ensureNonzeroAddress(_xvsStore);\n\n address oldXvsContract = xvsAddress;\n address oldStore = xvsStore;\n require(oldXvsContract == address(0), \"already initialized\");\n\n xvsAddress = _xvs;\n xvsStore = _xvsStore;\n\n _notEntered = true;\n\n emit StoreUpdated(oldXvsContract, oldStore, _xvs, _xvsStore);\n }\n\n /**\n * @notice Sets the address of the prime token contract\n * @param _primeToken address of the prime token contract\n * @param _primeRewardToken address of reward token\n * @param _primePoolId pool id for reward\n */\n function setPrimeToken(IPrime _primeToken, address _primeRewardToken, uint256 _primePoolId) external onlyAdmin {\n require(address(_primeToken) != address(0), \"prime token cannot be zero address\");\n require(_primeRewardToken != address(0), \"reward cannot be zero address\");\n\n _ensureValidPool(_primeRewardToken, _primePoolId);\n\n emit NewPrimeToken(primeToken, _primeToken, primeRewardToken, _primeRewardToken, primePoolId, _primePoolId);\n\n primeToken = _primeToken;\n primeRewardToken = _primeRewardToken;\n primePoolId = _primePoolId;\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlAddress New address for the access control\n */\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\n _setAccessControlManager(newAccessControlAddress);\n }\n\n /**\n * @dev Reverts if the provided address is a zero address\n * @param address_ Address to check\n */\n function _ensureNonzeroAddress(address address_) internal pure {\n require(address_ != address(0), \"zero address not allowed\");\n }\n\n /**\n * @dev Transfers the reward to the user, taking into account the rewards store\n * balance and the previous debt. If there are not enough rewards in the store,\n * transfers the available funds and records the debt amount in pendingRewardTransfers.\n * @param rewardToken Reward token address\n * @param userAddress User address\n * @param amount Reward amount, in reward tokens\n */\n function _transferReward(address rewardToken, address userAddress, uint256 amount) internal {\n address xvsStore_ = xvsStore;\n uint256 storeBalance = IBEP20(rewardToken).balanceOf(xvsStore_);\n uint256 debtDueToFailedTransfers = pendingRewardTransfers[rewardToken][userAddress];\n uint256 fullAmount = amount.add(debtDueToFailedTransfers);\n\n if (fullAmount <= storeBalance) {\n if (debtDueToFailedTransfers != 0) {\n pendingRewardTransfers[rewardToken][userAddress] = 0;\n emit VaultDebtUpdated(rewardToken, userAddress, debtDueToFailedTransfers, 0);\n }\n XVSStore(xvsStore_).safeRewardTransfer(rewardToken, userAddress, fullAmount);\n return;\n }\n // Overflow isn't possible due to the check above\n uint256 newOwedAmount = fullAmount - storeBalance;\n pendingRewardTransfers[rewardToken][userAddress] = newOwedAmount;\n emit VaultDebtUpdated(rewardToken, userAddress, debtDueToFailedTransfers, newOwedAmount);\n XVSStore(xvsStore_).safeRewardTransfer(rewardToken, userAddress, storeBalance);\n }\n\n /**\n * @dev Computes cumulative reward for all user's shares\n * @param user UserInfo storage struct\n * @param pool PoolInfo storage struct\n */\n function _cumulativeReward(UserInfo storage user, PoolInfo storage pool) internal view returns (uint256) {\n return user.amount.sub(user.pendingWithdrawals).mul(pool.accRewardPerShare).div(1e12);\n }\n\n /**\n * @dev Computes the reward for all user's shares\n * @param user UserInfo storage struct\n * @param pool PoolInfo storage struct\n */\n function _computeReward(UserInfo storage user, PoolInfo storage pool) internal view returns (uint256) {\n return _cumulativeReward(user, pool).sub(user.rewardDebt);\n }\n}\n" + }, + "contracts/XVSVault/XVSVaultErrorReporter.sol": { + "content": "pragma solidity ^0.5.16;\n\ncontract XVSVaultErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED\n }\n\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n" + }, + "contracts/XVSVault/XVSVaultProxy.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"./XVSVaultStorage.sol\";\nimport \"./XVSVaultErrorReporter.sol\";\n\n/**\n * @title XVS Vault Proxy\n * @author Venus\n * @notice XVS Vault Proxy contract\n */\ncontract XVSVaultProxy is XVSVaultAdminStorage, XVSVaultErrorReporter {\n /**\n * @notice Emitted when pendingXVSVaultImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingXVSVaultImplementation is accepted, which means XVS Vault implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor() public {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation = pendingXVSVaultImplementation;\n\n pendingXVSVaultImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new implementation of XVS Vault. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public returns (uint) {\n // Check caller is pendingImplementation\n if (msg.sender != pendingXVSVaultImplementation) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldImplementation = implementation;\n address oldPendingImplementation = pendingXVSVaultImplementation;\n\n implementation = pendingXVSVaultImplementation;\n\n pendingXVSVaultImplementation = address(0);\n\n emit NewImplementation(oldImplementation, implementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingXVSVaultImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\n // Check caller = admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n }\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n function() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize)\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize)\n }\n default {\n return(free_mem_ptr, returndatasize)\n }\n }\n }\n}\n" + }, + "contracts/XVSVault/XVSVaultStorage.sol": { + "content": "pragma solidity ^0.5.16;\n\nimport \"../Utils/SafeMath.sol\";\nimport \"../Utils/IBEP20.sol\";\nimport \"../Tokens/Prime/IPrime.sol\";\n\ncontract XVSVaultAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of XVS Vault\n */\n address public implementation;\n\n /**\n * @notice Pending brains of XVS Vault\n */\n address public pendingXVSVaultImplementation;\n}\n\ncontract XVSVaultStorageV1 is XVSVaultAdminStorage {\n /// @notice Guard variable for re-entrancy checks\n bool internal _notEntered;\n\n /// @notice The reward token store\n address public xvsStore;\n\n /// @notice The xvs token address\n address public xvsAddress;\n\n // Reward tokens created per block indentified by reward token address.\n mapping(address => uint256) public rewardTokenAmountsPerBlock;\n\n /// @notice Info of each user.\n struct UserInfo {\n uint256 amount;\n uint256 rewardDebt;\n uint256 pendingWithdrawals;\n }\n\n // Info of each pool.\n struct PoolInfo {\n IBEP20 token; // Address of token contract to stake.\n uint256 allocPoint; // How many allocation points assigned to this pool.\n uint256 lastRewardBlock; // Last block number that reward tokens distribution occurs.\n uint256 accRewardPerShare; // Accumulated per share, times 1e12. See below.\n uint256 lockPeriod; // Min time between withdrawal request and its execution.\n }\n\n // Infomation about a withdrawal request\n struct WithdrawalRequest {\n uint256 amount;\n uint128 lockedUntil;\n uint128 afterUpgrade;\n }\n\n // Info of each user that stakes tokens.\n mapping(address => mapping(uint256 => mapping(address => UserInfo))) internal userInfos;\n\n // Info of each pool.\n mapping(address => PoolInfo[]) public poolInfos;\n\n // Total allocation points. Must be the sum of all allocation points in all pools.\n mapping(address => uint256) public totalAllocPoints;\n\n // Info of requested but not yet executed withdrawals\n mapping(address => mapping(uint256 => mapping(address => WithdrawalRequest[]))) internal withdrawalRequests;\n\n /// @notice DEPRECATED A record of each accounts delegate (before the voting power fix)\n mapping(address => address) private __oldDelegatesSlot;\n\n /// @notice A checkpoint for marking number of votes from a given block\n struct Checkpoint {\n uint32 fromBlock;\n uint96 votes;\n }\n\n /// @notice DEPRECATED A record of votes checkpoints for each account, by index (before the voting power fix)\n mapping(address => mapping(uint32 => Checkpoint)) private __oldCheckpointsSlot;\n\n /// @notice DEPRECATED The number of checkpoints for each account (before the voting power fix)\n mapping(address => uint32) private __oldNumCheckpointsSlot;\n\n /// @notice A record of states for signing / validating signatures\n mapping(address => uint) public nonces;\n\n /// @notice The EIP-712 typehash for the contract's domain\n bytes32 public constant DOMAIN_TYPEHASH =\n keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n bytes32 public constant DELEGATION_TYPEHASH =\n keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n}\n\ncontract XVSVaultStorage is XVSVaultStorageV1 {\n /// @notice A record of each accounts delegate\n mapping(address => address) public delegates;\n\n /// @notice A record of votes checkpoints for each account, by index\n mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n /// @notice The number of checkpoints for each account\n mapping(address => uint32) public numCheckpoints;\n\n /// @notice Tracks pending withdrawals for all users for a particular reward token and pool id\n mapping(address => mapping(uint256 => uint256)) internal totalPendingWithdrawals;\n\n /// @notice pause indicator for Vault\n bool public vaultPaused;\n\n /// @notice if the token is added to any of the pools\n mapping(address => bool) public isStakedToken;\n\n /// @notice Amount we owe to users because of failed transfer attempts\n mapping(address => mapping(address => uint256)) public pendingRewardTransfers;\n\n /// @notice Prime token contract address\n IPrime public primeToken;\n\n /// @notice Reward token for which prime token is issued for staking\n address public primeRewardToken;\n\n /// @notice Pool ID for which prime token is issued for staking\n uint256 public primePoolId;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[46] private __gap;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +}