diff --git a/contracts/Auth2.sol b/contracts/Auth2.sol index 377aeb2..d5dfa0b 100644 --- a/contracts/Auth2.sol +++ b/contracts/Auth2.sol @@ -7,38 +7,53 @@ pragma solidity 0.7.6; import "./VaultParameters.sol"; - /** * @title Auth2 - * @dev Manages USDP's system access - * @dev copy of Auth from VaultParameters.sol but with immutable vaultParameters for saving gas - **/ + * @notice Auth2 is a contract that manages USDP's system access with immutable vaultParameters for gas optimization. + * @dev Inherits VaultParameters contract's properties for access control. + * @dev Copy of Auth from VaultParameters.sol but with immutable vaultParameters for saving gas + */ contract Auth2 { - // address of the the contract with vault parameters + /** + * @notice The VaultParameters contract which holds system parameters. + * @dev Immutable to save gas, as it's set only once upon construction and cannot be changed afterwards. + */ VaultParameters public immutable vaultParameters; + /** + * @notice Constructs the Auth2 contract. + * @param _parameters The address of the VaultParameters contract. + */ constructor(address _parameters) { require(_parameters != address(0), "Unit Protocol: ZERO_ADDRESS"); - vaultParameters = VaultParameters(_parameters); } - // ensures tx's sender is a manager + /** + * @notice Ensures the transaction's sender is a manager. + * @dev Modifier that throws if the sender is not a manager. + */ modifier onlyManager() { require(vaultParameters.isManager(msg.sender), "Unit Protocol: AUTH_FAILED"); _; } - // ensures tx's sender is able to modify the Vault + /** + * @notice Ensures the transaction's sender has access to modify the Vault. + * @dev Modifier that throws if the sender cannot modify the Vault. + */ modifier hasVaultAccess() { require(vaultParameters.canModifyVault(msg.sender), "Unit Protocol: AUTH_FAILED"); _; } - // ensures tx's sender is the Vault + /** + * @notice Ensures the transaction's sender is the Vault itself. + * @dev Modifier that throws if the sender is not the Vault. + */ modifier onlyVault() { require(msg.sender == vaultParameters.vault(), "Unit Protocol: AUTH_FAILED"); _; } -} +} \ No newline at end of file diff --git a/contracts/CDPRegistry.sol b/contracts/CDPRegistry.sol index b220c1c..858f843 100644 --- a/contracts/CDPRegistry.sol +++ b/contracts/CDPRegistry.sol @@ -9,7 +9,10 @@ pragma experimental ABIEncoderV2; import "./interfaces/IVault.sol"; import "./interfaces/ICollateralRegistry.sol"; - +/** + * @title CDPRegistry + * @dev Contract to manage a registry of collateralized debt positions (CDPs) for the Unit Protocol. + */ contract CDPRegistry { struct CDP { @@ -26,12 +29,22 @@ contract CDPRegistry { event Added(address indexed asset, address indexed owner); event Removed(address indexed asset, address indexed owner); + /** + * @dev Constructs the CDPRegistry contract. + * @param _vault Address of the IVault contract. + * @param _collateralRegistry Address of the ICollateralRegistry contract. + */ constructor (address _vault, address _collateralRegistry) { require(_vault != address(0) && _collateralRegistry != address(0), "Unit Protocol: ZERO_ADDRESS"); vault = IVault(_vault); cr = ICollateralRegistry(_collateralRegistry); } + /** + * @dev Updates the CDP registry for a given asset and owner. + * @param asset Address of the asset. + * @param owner Address of the owner. + */ function checkpoint(address asset, address owner) public { require(asset != address(0) && owner != address(0), "Unit Protocol: ZERO_ADDRESS"); @@ -45,12 +58,22 @@ contract CDPRegistry { } } + /** + * @dev Updates the CDP registry for a given asset and multiple owners. + * @param asset Address of the asset. + * @param owners Array of owner addresses. + */ function batchCheckpointForAsset(address asset, address[] calldata owners) external { for (uint i = 0; i < owners.length; i++) { checkpoint(asset, owners[i]); } } + /** + * @dev Updates the CDP registry for multiple assets and owners. + * @param assets Array of asset addresses. + * @param owners Array of owner addresses. + */ function batchCheckpoint(address[] calldata assets, address[] calldata owners) external { require(assets.length == owners.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < owners.length; i++) { @@ -58,15 +81,32 @@ contract CDPRegistry { } } + /** + * @dev Checks if a CDP is active. + * @param asset Address of the asset. + * @param owner Address of the owner. + * @return alive Boolean indicating if the CDP is active. + */ function isAlive(address asset, address owner) public view returns (bool) { return vault.debts(asset, owner) != 0; } + /** + * @dev Checks if a CDP is listed in the registry. + * @param asset Address of the asset. + * @param owner Address of the owner. + * @return listed Boolean indicating if the CDP is listed. + */ function isListed(address asset, address owner) public view returns (bool) { if (cdpList[asset].length == 0) { return false; } return cdpIndex[asset][owner] != 0 || cdpList[asset][0] == owner; } + /** + * @dev Internal function to remove a CDP from the registry. + * @param asset Address of the asset. + * @param owner Address of the owner. + */ function _removeCdp(address asset, address owner) internal { uint id = cdpIndex[asset][owner]; @@ -85,6 +125,11 @@ contract CDPRegistry { emit Removed(asset, owner); } + /** + * @dev Internal function to add a CDP to the registry. + * @param asset Address of the asset. + * @param owner Address of the owner. + */ function _addCdp(address asset, address owner) internal { cdpIndex[asset][owner] = cdpList[asset].length; cdpList[asset].push(owner); @@ -92,6 +137,11 @@ contract CDPRegistry { emit Added(asset, owner); } + /** + * @dev Retrieves the list of CDPs for a given collateral. + * @param asset Address of the asset. + * @return cdps Array of CDP structs. + */ function getCdpsByCollateral(address asset) external view returns (CDP[] memory cdps) { address[] memory owners = cdpList[asset]; cdps = new CDP[](owners.length); @@ -100,6 +150,11 @@ contract CDPRegistry { } } + /** + * @dev Retrieves the list of CDPs for a given owner. + * @param owner Address of the owner. + * @return r Array of CDP structs. + */ function getCdpsByOwner(address owner) external view returns (CDP[] memory r) { address[] memory assets = cr.collaterals(); CDP[] memory cdps = new CDP[](assets.length); @@ -116,9 +171,12 @@ contract CDPRegistry { for (uint i = 0; i < actualCdpsCount; i++) { r[i] = cdps[i]; } - } + /** + * @dev Retrieves the list of all CDPs in the registry. + * @return r Array of CDP structs. + */ function getAllCdps() external view returns (CDP[] memory r) { uint totalCdpCount = getCdpsCount(); @@ -135,6 +193,10 @@ contract CDPRegistry { } } + /** + * @dev Retrieves the total count of CDPs in the registry. + * @return totalCdpCount The total count of CDPs. + */ function getCdpsCount() public view returns (uint totalCdpCount) { address[] memory assets = cr.collaterals(); for (uint i = 0; i < assets.length; i++) { @@ -142,6 +204,11 @@ contract CDPRegistry { } } + /** + * @dev Retrieves the count of CDPs for a given collateral. + * @param asset Address of the asset. + * @return The count of CDPs for the given collateral. + */ function getCdpsCountForCollateral(address asset) public view returns (uint) { return cdpList[asset].length; } diff --git a/contracts/CollateralRegistry.sol b/contracts/CollateralRegistry.sol index c6ef199..cb0223d 100644 --- a/contracts/CollateralRegistry.sol +++ b/contracts/CollateralRegistry.sol @@ -6,22 +6,41 @@ pragma solidity ^0.7.1; pragma experimental ABIEncoderV2; - import "./VaultParameters.sol"; - /** * @title CollateralRegistry - **/ + * @dev Manages a registry of collateral assets for Unit Protocol. + */ contract CollateralRegistry is Auth { + /** + * @dev Emitted when a new collateral is added to the registry. + * @param asset The address of the collateral asset added. + */ event CollateralAdded(address indexed asset); + + /** + * @dev Emitted when a collateral is removed from the registry. + * @param asset The address of the collateral asset removed. + */ event CollateralRemoved(address indexed asset); + /** + * @dev Mapping from collateral asset addresses to their respective ID. + */ mapping(address => uint) public collateralId; + /** + * @dev List of all collateral asset addresses. + */ address[] public collateralList; - + + /** + * @dev Initializes the contract with a list of collateral assets. + * @param _vaultParameters The address of the VaultParameters contract. + * @param assets The initial list of collateral asset addresses. + */ constructor(address _vaultParameters, address[] memory assets) Auth(_vaultParameters) { for (uint i = 0; i < assets.length; i++) { require(!isCollateral(assets[i]), "Unit Protocol: ALREADY_EXIST"); @@ -31,49 +50,62 @@ contract CollateralRegistry is Auth { } } + /** + * @dev Adds a new collateral asset to the registry. + * @param asset The address of the collateral asset to add. + * @notice Only the manager can call this function. + */ function addCollateral(address asset) public onlyManager { require(asset != address(0), "Unit Protocol: ZERO_ADDRESS"); - require(!isCollateral(asset), "Unit Protocol: ALREADY_EXIST"); - collateralId[asset] = collateralList.length; collateralList.push(asset); - emit CollateralAdded(asset); } + /** + * @dev Removes a collateral asset from the registry. + * @param asset The address of the collateral asset to remove. + * @notice Only the manager can call this function. + */ function removeCollateral(address asset) public onlyManager { require(asset != address(0), "Unit Protocol: ZERO_ADDRESS"); - require(isCollateral(asset), "Unit Protocol: DOES_NOT_EXIST"); - uint id = collateralId[asset]; - delete collateralId[asset]; - uint lastId = collateralList.length - 1; - if (id != lastId) { address lastCollateral = collateralList[lastId]; collateralList[id] = lastCollateral; collateralId[lastCollateral] = id; } - collateralList.pop(); - emit CollateralRemoved(asset); } + /** + * @dev Checks if an address is a collateral in the registry. + * @param asset The address to check. + * @return True if the address is a collateral, false otherwise. + */ function isCollateral(address asset) public view returns(bool) { if (collateralList.length == 0) { return false; } return collateralId[asset] != 0 || collateralList[0] == asset; } + /** + * @dev Returns the list of all collateral assets in the registry. + * @return An array of addresses of the collateral assets. + */ function collaterals() external view returns (address[] memory) { return collateralList; } + /** + * @dev Returns the count of collateral assets in the registry. + * @return The count of collateral assets. + */ function collateralsCount() external view returns (uint) { return collateralList.length; } -} +} \ No newline at end of file diff --git a/contracts/Migrations.sol b/contracts/Migrations.sol index a12737e..0779f24 100644 --- a/contracts/Migrations.sol +++ b/contracts/Migrations.sol @@ -1,21 +1,41 @@ // SPDX-License-Identifier: bsl-1.1 - pragma solidity 0.7.6; +/* + * @title Migrations + * @dev This contract is used to manage migrations of the smart contract code. + * It keeps track of the last completed migration script. + */ contract Migrations { + /* @dev Address of the contract owner. */ address public owner; + + /* @dev Stores the last completed migration script number. */ uint public last_completed_migration; + /* + * @dev Sets the original owner of the contract to the sender account on contract creation. + */ constructor() { owner = msg.sender; } + /* + * @dev Modifier to restrict the execution of functions to only the owner of the contract. + * Reverts if the sender is not the owner. + */ modifier restricted() { if (msg.sender == owner) _; + _; } + /* + * @notice Sets the last completed migration script number. + * @param completed The number of the last completed migration. + * @dev Can only be called by the current owner of the contract. + */ function setCompleted(uint completed) public restricted { last_completed_migration = completed; } -} +} \ No newline at end of file diff --git a/contracts/ParametersBatchUpdater.sol b/contracts/ParametersBatchUpdater.sol index c983c90..e93e3b2 100644 --- a/contracts/ParametersBatchUpdater.sol +++ b/contracts/ParametersBatchUpdater.sol @@ -6,7 +6,6 @@ pragma solidity 0.7.6; pragma abicoder v2; - import "./VaultParameters.sol"; import "./interfaces/vault-managers/parameters/IVaultManagerParameters.sol"; import "./interfaces/IBearingAssetOracle.sol"; @@ -14,10 +13,9 @@ import "./interfaces/IOracleRegistry.sol"; import "./interfaces/ICollateralRegistry.sol"; import "./interfaces/IVault.sol"; - -/** - * @title ParametersBatchUpdater - **/ +/* + * Contract for batch updating parameters related to vaults. + */ contract ParametersBatchUpdater is Auth { IVaultManagerParameters public immutable vaultManagerParameters; @@ -26,6 +24,12 @@ contract ParametersBatchUpdater is Auth { uint public constant BEARING_ASSET_ORACLE_TYPE = 9; + /* + * Sets vault manager parameters, oracle registry, and collateral registry. + * @param _vaultManagerParameters The address of the vault manager parameters contract. + * @param _oracleRegistry The address of the oracle registry contract. + * @param _collateralRegistry The address of the collateral registry contract. + */ constructor( address _vaultManagerParameters, address _oracleRegistry, @@ -40,12 +44,11 @@ contract ParametersBatchUpdater is Auth { collateralRegistry = ICollateralRegistry(_collateralRegistry); } - /** - * @notice Only manager is able to call this function - * @dev Grants and revokes manager's status - * @param who The array of target addresses - * @param permit The array of permission flags - **/ + /* + * Updates manager status for multiple addresses. + * @param who The addresses to update. + * @param permit The manager statuses to set. + */ function setManagers(address[] calldata who, bool[] calldata permit) external onlyManager { require(who.length == permit.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < who.length; i++) { @@ -53,12 +56,11 @@ contract ParametersBatchUpdater is Auth { } } - /** - * @notice Only manager is able to call this function - * @dev Sets a permission for provided addresses to modify the Vault - * @param who The array of target addresses - * @param permit The array of permission flags - **/ + /* + * Updates Vault access permissions for multiple addresses. + * @param who The addresses to update. + * @param permit The access permissions to set. + */ function setVaultAccesses(address[] calldata who, bool[] calldata permit) external onlyManager { require(who.length == permit.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < who.length; i++) { @@ -66,12 +68,11 @@ contract ParametersBatchUpdater is Auth { } } - /** - * @notice Only manager is able to call this function - * @dev Sets the percentage of the year stability fee for a particular collateral - * @param assets The array of addresses of the main collateral tokens - * @param newValues The array of stability fee percentages (3 decimals) - **/ + /* + * Updates the stability fee for multiple collaterals. + * @param assets The collateral tokens to update. + * @param newValues The stability fees to set. + */ function setStabilityFees(address[] calldata assets, uint[] calldata newValues) public onlyManager { require(assets.length == newValues.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -79,12 +80,11 @@ contract ParametersBatchUpdater is Auth { } } - /** - * @notice Only manager is able to call this function - * @dev Sets the percentages of the liquidation fee for provided collaterals - * @param assets The array of addresses of the main collateral tokens - * @param newValues The array of liquidation fee percentages (0 decimals) - **/ + /* + * Updates the liquidation fee for multiple collaterals. + * @param assets The collateral tokens to update. + * @param newValues The liquidation fees to set. + */ function setLiquidationFees(address[] calldata assets, uint[] calldata newValues) public onlyManager { require(assets.length == newValues.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -92,13 +92,12 @@ contract ParametersBatchUpdater is Auth { } } - /** - * @notice Only manager is able to call this function - * @dev Enables/disables oracle types - * @param _types The array of types of the oracles - * @param assets The array of addresses of the main collateral tokens - * @param flags The array of control flags - **/ + /* + * Enables or disables oracle types for multiple collaterals. + * @param _types The oracle types to update. + * @param assets The collateral tokens to update. + * @param flags The enablement statuses to set. + */ function setOracleTypes(uint[] calldata _types, address[] calldata assets, bool[] calldata flags) public onlyManager { require(_types.length == assets.length && _types.length == flags.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < _types.length; i++) { @@ -106,12 +105,11 @@ contract ParametersBatchUpdater is Auth { } } - /** - * @notice Only manager is able to call this function - * @dev Sets USDP limits for a provided collaterals - * @param assets The addresses of the main collateral tokens - * @param limits The borrow USDP limits - **/ + /* + * Updates the USDP borrow limits for multiple collaterals. + * @param assets The collateral tokens to update. + * @param limits The USDP borrow limits to set. + */ function setTokenDebtLimits(address[] calldata assets, uint[] calldata limits) public onlyManager { require(assets.length == limits.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -119,6 +117,12 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Changes the oracle types for multiple collaterals and users. + * @param assets The collateral tokens to update. + * @param users The user addresses to update. + * @param oracleTypes The new oracle types to set. + */ function changeOracleTypes(address[] calldata assets, address[] calldata users, uint[] calldata oracleTypes) public onlyManager { require(assets.length == users.length && assets.length == oracleTypes.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -126,6 +130,11 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Updates the initial collateral ratios for multiple collaterals. + * @param assets The collateral tokens to update. + * @param values The initial collateral ratios to set. + */ function setInitialCollateralRatios(address[] calldata assets, uint[] calldata values) public onlyManager { require(assets.length == values.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -133,6 +142,11 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Updates the liquidation ratios for multiple collaterals. + * @param assets The collateral tokens to update. + * @param values The liquidation ratios to set. + */ function setLiquidationRatios(address[] calldata assets, uint[] calldata values) public onlyManager { require(assets.length == values.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -140,6 +154,11 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Updates the liquidation discounts for multiple collaterals. + * @param assets The collateral tokens to update. + * @param values The liquidation discounts to set. + */ function setLiquidationDiscounts(address[] calldata assets, uint[] calldata values) public onlyManager { require(assets.length == values.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -147,6 +166,11 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Updates the devaluation periods for multiple collaterals. + * @param assets The collateral tokens to update. + * @param values The devaluation periods to set. + */ function setDevaluationPeriods(address[] calldata assets, uint[] calldata values) public onlyManager { require(assets.length == values.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -154,6 +178,11 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Updates oracle types in the oracle registry for multiple oracles. + * @param oracleTypes The oracle types to update. + * @param oracles The oracle addresses to update. + */ function setOracleTypesInRegistry(uint[] calldata oracleTypes, address[] calldata oracles) public onlyManager { require(oracleTypes.length == oracles.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < oracleTypes.length; i++) { @@ -161,6 +190,11 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Associates oracle types with multiple assets in the oracle registry. + * @param assets The asset addresses to update. + * @param oracleTypes The oracle types to associate. + */ function setOracleTypesToAssets(address[] calldata assets, uint[] calldata oracleTypes) public onlyManager { require(oracleTypes.length == assets.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -168,6 +202,11 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Batch sets oracle types for arrays of assets in the oracle registry. + * @param assets Array of arrays of asset addresses. + * @param oracleTypes The oracle types to set. + */ function setOracleTypesToAssetsBatch(address[][] calldata assets, uint[] calldata oracleTypes) public onlyManager { require(oracleTypes.length == assets.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < assets.length; i++) { @@ -175,6 +214,11 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Sets the underlying assets for multiple bearing assets in the oracle registry. + * @param bearings The bearing asset addresses to update. + * @param underlyings The underlying asset addresses to set. + */ function setUnderlyings(address[] calldata bearings, address[] calldata underlyings) public onlyManager { require(bearings.length == underlyings.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); for (uint i = 0; i < bearings.length; i++) { @@ -182,6 +226,18 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Sets multiple parameters for collateral assets. + * @param assets The collateral asset addresses to update. + * @param stabilityFeeValue The stability fee value for all assets. + * @param liquidationFeeValue The liquidation fee value for all assets. + * @param initialCollateralRatioValue The initial collateral ratio value for all assets. + * @param liquidationRatioValue The liquidation ratio value for all assets. + * @param liquidationDiscountValue The liquidation discount value for all assets. + * @param devaluationPeriodValue The devaluation period value for all assets. + * @param usdpLimit The USDP limit for all assets. + * @param oracles The oracle addresses for all assets. + */ function setCollaterals( address[] calldata assets, uint stabilityFeeValue, @@ -212,9 +268,14 @@ contract ParametersBatchUpdater is Auth { } } + /* + * Adds or removes collateral addresses in the collateral registry. + * @param assets The collateral asset addresses to update. + * @param add Whether to add (true) or remove (false) the addresses. + */ function setCollateralAddresses(address[] calldata assets, bool add) external onlyManager { for (uint i = 0; i < assets.length; i++) { add ? collateralRegistry.addCollateral(assets[i]) : collateralRegistry.removeCollateral(assets[i]); } } -} +} \ No newline at end of file diff --git a/contracts/USDP.sol b/contracts/USDP.sol index 96e2852..615c6fb 100644 --- a/contracts/USDP.sol +++ b/contracts/USDP.sol @@ -8,11 +8,11 @@ pragma solidity 0.7.6; import "./VaultParameters.sol"; import "./helpers/SafeMath.sol"; - -/** - * @title USDP token implementation - * @dev ERC20 token - **/ +/* + * @title USDP Stablecoin Contract + * @notice Implements the operations of the USDP Stablecoin + * @dev This contract handles minting, burning, and transferring of USDP tokens. + */ contract USDP is Auth { using SafeMath for uint; @@ -166,6 +166,12 @@ contract USDP is Auth { return true; } + /** + * @dev Internal function to set approval of tokens for a given spender + * @param owner The address of the token owner + * @param spender The address of the spender + * @param amount The amount of tokens to approve + */ function _approve(address owner, address spender, uint amount) internal virtual { require(owner != address(0), "Unit Protocol: approve from the zero address"); require(spender != address(0), "Unit Protocol: approve to the zero address"); @@ -174,10 +180,15 @@ contract USDP is Auth { emit Approval(owner, spender, amount); } + /** + * @dev Internal function to burn tokens from a given address + * @param from The address from which tokens will be burned + * @param amount The amount of tokens to burn + */ function _burn(address from, uint amount) internal virtual { balanceOf[from] = balanceOf[from].sub(amount); totalSupply = totalSupply.sub(amount); emit Transfer(from, address(0), amount); } -} +} \ No newline at end of file diff --git a/contracts/auction/LiquidationAuction02.sol b/contracts/auction/LiquidationAuction02.sol index 34e2514..aa1c4ae 100644 --- a/contracts/auction/LiquidationAuction02.sol +++ b/contracts/auction/LiquidationAuction02.sol @@ -21,7 +21,8 @@ import '../helpers/SafeMath.sol'; /** * @title LiquidationAuction02 - **/ + * @dev Contract to manage the liquidation auction process for collateralized debt positions. + */ contract LiquidationAuction02 is ReentrancyGuard { using SafeMath for uint; @@ -34,20 +35,32 @@ contract LiquidationAuction02 is ReentrancyGuard { uint public constant WRAPPED_TO_UNDERLYING_ORACLE_TYPE = 11; /** - * @dev Trigger when buyouts are happened - **/ + * @dev Emitted when a buyout occurs. + * @param asset Address of the collateral asset. + * @param owner Address of the owner of the position. + * @param buyer Address of the buyer. + * @param amount Amount of collateral bought out. + * @param price Price at which the buyout occurred. + * @param penalty Liquidation penalty applied. + */ event Buyout(address indexed asset, address indexed owner, address indexed buyer, uint amount, uint price, uint penalty); + /** + * @dev Modifier to create a checkpoint in CDP registry after function execution. + * @param asset Address of the collateral asset. + * @param owner Address of the owner of the position. + */ modifier checkpoint(address asset, address owner) { _; cdpRegistry.checkpoint(asset, owner); } /** - * @param _vaultManagerParameters The address of the contract with Vault manager parameters - * @param _cdpRegistry The address of the CDP registry - * @param _assetsBooleanParameters The address of the AssetsBooleanParameters - **/ + * @dev Constructs the LiquidationAuction02 contract. + * @param _vaultManagerParameters The address of the contract with Vault manager parameters. + * @param _cdpRegistry The address of the CDP registry. + * @param _assetsBooleanParameters The address of the AssetsBooleanParameters. + */ constructor(address _vaultManagerParameters, address _cdpRegistry, address _assetsBooleanParameters) { require( _vaultManagerParameters != address(0) && @@ -62,10 +75,10 @@ contract LiquidationAuction02 is ReentrancyGuard { } /** - * @dev Buyouts a position's collateral - * @param asset The address of the main collateral token of a position - * @param owner The owner of a position - **/ + * @dev Buyouts a position's collateral. + * @param asset The address of the main collateral token of a position. + * @param owner The owner of a position. + */ function buyout(address asset, address owner) public nonReentrant checkpoint(asset, owner) { require(vault.liquidationBlock(asset, owner) != 0, "Unit Protocol: LIQUIDATION_NOT_TRIGGERED"); uint startingPrice = vault.liquidationPrice(asset, owner); @@ -110,6 +123,15 @@ contract LiquidationAuction02 is ReentrancyGuard { ); } + /** + * @dev Internal function to liquidate a position. + * @param asset Address of the collateral asset. + * @param user Address of the user whose position is being liquidated. + * @param collateralToBuyer Amount of collateral to be given to the buyer. + * @param collateralToOwner Amount of collateral to be returned to the owner. + * @param repayment Amount to be repaid. + * @param penalty Liquidation penalty to be applied. + */ function _liquidate( address asset, address user, @@ -134,6 +156,17 @@ contract LiquidationAuction02 is ReentrancyGuard { emit Buyout(asset, user, msg.sender, collateralToBuyer, repayment, penalty); } + /** + * @dev Internal pure function to calculate liquidation parameters. + * @param depreciationPeriod Period over which the asset price depreciates. + * @param blocksPast Number of blocks passed since liquidation was triggered. + * @param startingPrice Starting price of the asset at liquidation trigger. + * @param debtWithPenalty Total debt including the penalty. + * @param collateralInPosition Amount of collateral in the position. + * @return collateralToBuyer Amount of collateral that goes to the buyer. + * @return collateralToOwner Amount of collateral that goes to the owner. + * @return price Repayment amount. + */ function _calcLiquidationParams( uint depreciationPeriod, uint blocksPast, @@ -163,4 +196,4 @@ contract LiquidationAuction02 is ReentrancyGuard { collateralToBuyer = collateralInPosition; } } -} +} \ No newline at end of file diff --git a/contracts/helpers/AssetParametersViewer.sol b/contracts/helpers/AssetParametersViewer.sol index 3e636f8..2833c7e 100644 --- a/contracts/helpers/AssetParametersViewer.sol +++ b/contracts/helpers/AssetParametersViewer.sol @@ -28,6 +28,9 @@ contract AssetParametersViewer { IVaultManagerBorrowFeeParameters public immutable vaultManagerBorrowFeeParameters; IAssetsBooleanParameters public immutable assetsBooleanParameters; + /** + * @dev Struct to hold asset parameters. + */ struct AssetParametersStruct { // asset address address asset; @@ -69,7 +72,12 @@ contract AssetParametersViewer { bool forceMoveWrappedAssetPositionOnLiquidation; } - + /** + * @notice Constructs the AssetParametersViewer contract. + * @param _vaultManagerParameters Address of the VaultManagerParameters contract. + * @param _vaultManagerBorrowFeeParameters Address of the VaultManagerBorrowFeeParameters contract. + * @param _assetsBooleanParameters Address of the AssetsBooleanParameters contract. + */ constructor( address _vaultManagerParameters, address _vaultManagerBorrowFeeParameters, @@ -83,9 +91,10 @@ contract AssetParametersViewer { } /** - * @notice Get parameters of one asset - * @param asset asset address - * @param maxOracleTypesToSearch since complete list of oracle types is unknown, we'll check types up to this number + * @notice Retrieves parameters for a single asset. + * @param asset The address of the asset to retrieve parameters for. + * @param maxOracleTypesToSearch The maximum number of oracle types to search through. + * @return r A struct containing the asset's parameters. */ function getAssetParameters(address asset, uint maxOracleTypesToSearch) public @@ -129,9 +138,10 @@ contract AssetParametersViewer { } /** - * @notice Get parameters of many assets - * @param assets asset addresses - * @param maxOracleTypesToSearch since complete list of oracle types is unknown, we'll check types up to this number + * @notice Retrieves parameters for multiple assets. + * @param assets An array of asset addresses to retrieve parameters for. + * @param maxOracleTypesToSearch The maximum number of oracle types to search through for each asset. + * @return r An array of structs, each containing parameters for the respective asset. */ function getMultiAssetParameters(address[] calldata assets, uint maxOracleTypesToSearch) external @@ -144,4 +154,4 @@ contract AssetParametersViewer { r[i] = getAssetParameters(assets[i], maxOracleTypesToSearch); } } -} +} \ No newline at end of file diff --git a/contracts/helpers/CDPViewer.sol b/contracts/helpers/CDPViewer.sol index 0b8df6a..0cb5899 100644 --- a/contracts/helpers/CDPViewer.sol +++ b/contracts/helpers/CDPViewer.sol @@ -18,7 +18,8 @@ import "./ERC20Like.sol"; /** - * @notice Views collaterals in one request to save node requests and speed up dapps. + * @title CDPViewer + * @notice Provides batch views for collateral debt positions (CDPs) and token details to optimize node requests. */ contract CDPViewer { @@ -86,22 +87,25 @@ contract CDPViewer { } struct TokenDetails { - address[2] lpUnderlyings; - uint128 balance; - uint128 totalSupply; - uint8 decimals; - address uniswapV2Factory; - - address underlyingToken; - uint256 underlyingTokenBalance; - uint256 underlyingTokenTotalSupply; - uint8 underlyingTokenDecimals; - address underlyingTokenUniswapV2Factory; - address[2] underlyingTokenUnderlyings; - + address[2] lpUnderlyings; // Addresses of underlying tokens for LP tokens + uint128 balance; // Token balance of the owner + uint128 totalSupply; // Total supply of the token + uint8 decimals; // Decimals of the token + address uniswapV2Factory; // Address of the Uniswap V2 factory + address underlyingToken; // Address of the underlying token for wrapped tokens + uint256 underlyingTokenBalance; // Balance of the underlying token + uint256 underlyingTokenTotalSupply; // Total supply of the underlying token + uint8 underlyingTokenDecimals; // Decimals of the underlying token + address underlyingTokenUniswapV2Factory; // Uniswap V2 factory for the underlying token + address[2] underlyingTokenUnderlyings; // Underlying tokens for the underlying LP token } - + /** + * @dev Initializes the contract by setting the vault manager parameters, oracle registry, and vault manager borrow fee parameters. + * @param _vaultManagerParameters Address of the vault manager parameters contract. + * @param _oracleRegistry Address of the oracle registry contract. + * @param _vaultManagerBorrowFeeParameters Address of the vault manager borrow fee parameters contract. + */ constructor(address _vaultManagerParameters, address _oracleRegistry, address _vaultManagerBorrowFeeParameters) { IVaultManagerParameters vmp = IVaultManagerParameters(_vaultManagerParameters); vaultManagerParameters = vmp; @@ -113,9 +117,10 @@ contract CDPViewer { } /** - * @notice Get parameters of one asset - * @param asset asset address - * @param owner owner address + * @notice Retrieves parameters and CDP information for a given asset and owner. + * @param asset The address of the asset to query. + * @param owner The address of the owner to query. + * @return r The CollateralParameters structure containing the requested information. */ function getCollateralParameters(address asset, address owner) public @@ -146,9 +151,10 @@ contract CDPViewer { } /** - * @notice Get details of one token - * @param asset token address - * @param owner owner address + * @notice Retrieves token details for a given asset and optionally for an owner's balance. + * @param asset The address of the token to query. + * @param owner The address of the owner to query, or zero address for no balance query. + * @return r The TokenDetails structure containing the requested information. */ function getTokenDetails(address asset, address owner) public @@ -195,12 +201,22 @@ contract CDPViewer { } } + /** + * @dev Converts bytes to an address. + * @param _bytes The bytes to convert. + * @return addr The converted address. + */ function bytesToAddress(bytes memory _bytes) private pure returns (address addr) { assembly { addr := mload(add(_bytes, 32)) } } + /** + * @dev Converts bytes to a bytes32. + * @param _bytes The bytes to convert. + * @return _bytes32 The converted bytes32. + */ function bytesToBytes32(bytes memory _bytes) private pure returns (bytes32 _bytes32) { assembly { _bytes32 := mload(add(_bytes, 32)) @@ -208,9 +224,10 @@ contract CDPViewer { } /** - * @notice Get parameters of many collaterals - * @param assets asset addresses - * @param owner owner address + * @notice Retrieves parameters for multiple collaterals and an owner. + * @param assets An array of asset addresses to query. + * @param owner The address of the owner to query. + * @return r An array of CollateralParameters structures containing the requested information. */ function getMultiCollateralParameters(address[] calldata assets, address owner) external @@ -225,9 +242,10 @@ contract CDPViewer { } /** - * @notice Get details of many token - * @param assets token addresses - * @param owner owner address + * @notice Retrieves details for multiple tokens and optionally for an owner's balances. + * @param assets An array of token addresses to query. + * @param owner The address of the owner to query, or zero address for no balance query. + * @return r An array of TokenDetails structures containing the requested information. */ function getMultiTokenDetails(address[] calldata assets, address owner) external @@ -240,4 +258,4 @@ contract CDPViewer { r[i] = getTokenDetails(assets[i], owner); } } -} +} \ No newline at end of file diff --git a/contracts/helpers/ERC20Like.sol b/contracts/helpers/ERC20Like.sol index 9dc3c93..df05e5f 100644 --- a/contracts/helpers/ERC20Like.sol +++ b/contracts/helpers/ERC20Like.sol @@ -5,11 +5,45 @@ */ pragma solidity 0.7.6; - +/** + * @title ERC20Like + * @dev Interface for the subset of the ERC20 standard. + */ interface ERC20Like { - function balanceOf(address) external view returns (uint); + /** + * @dev Returns the amount of tokens owned by `account`. + * @param account The address of the account to check. + * @return The amount of tokens owned. + */ + function balanceOf(address account) external view returns (uint); + + /** + * @dev Returns the number of decimals used to get its user representation. + * @return The number of decimals for this token. + */ function decimals() external view returns (uint8); - function transfer(address, uint256) external returns (bool); - function transferFrom(address, address, uint256) external returns (bool); + + /** + * @dev Moves `amount` tokens from the caller's account to `recipient`. + * @param recipient The address of the recipient. + * @param amount The amount of tokens to be transferred. + * @return A boolean value indicating whether the operation succeeded. + */ + function transfer(address recipient, uint256 amount) external returns (bool); + + /** + * @dev Moves `amount` tokens from `sender` to `recipient` using the allowance mechanism. + * `amount` is then deducted from the caller's allowance. + * @param sender The address of the sender. + * @param recipient The address of the recipient. + * @param amount The amount of tokens to be transferred. + * @return A boolean value indicating whether the operation succeeded. + */ + function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + + /** + * @dev Returns the total token supply in existence. + * @return The total token supply. + */ function totalSupply() external view returns (uint256); -} +} \ No newline at end of file diff --git a/contracts/helpers/IUniswapV2Factory.sol b/contracts/helpers/IUniswapV2Factory.sol index 358150e..7109d5f 100644 --- a/contracts/helpers/IUniswapV2Factory.sol +++ b/contracts/helpers/IUniswapV2Factory.sol @@ -5,15 +5,57 @@ */ pragma solidity 0.7.6; +/** + * @title IUniswapV2Factory + * @dev Interface for the Uniswap V2 Factory. + */ interface IUniswapV2Factory { + /** + * @dev Emitted when a new pair is created. + * @param token0 The address of the first token. + * @param token1 The address of the second token. + * @param pair The address of the created pair. + */ event PairCreated(address indexed token0, address indexed token1, address pair, uint); + /** + * @dev Returns the address of the pair for tokenA and tokenB, if it exists. + * @param tokenA The address of the first token. + * @param tokenB The address of the second token. + * @return pair The address of the pair. + */ function getPair(address tokenA, address tokenB) external view returns (address pair); - function allPairs(uint) external view returns (address pair); + + /** + * @dev Returns the address of the n-th pair. + * @param index The index of the pair in the list of all pairs. + * @return pair The address of the pair. + */ + function allPairs(uint index) external view returns (address pair); + + /** + * @dev Returns the total number of pairs. + * @return The total number of pairs. + */ function allPairsLength() external view returns (uint); + /** + * @dev Returns the fee to address. + * @return The address to which fees are sent. + */ function feeTo() external view returns (address); + + /** + * @dev Returns the address allowed to set feeTo. + * @return The address allowed to set feeTo. + */ function feeToSetter() external view returns (address); + /** + * @dev Creates a pair for two tokens and returns the pair's address. + * @param tokenA The address of the first token. + * @param tokenB The address of the second token. + * @return pair The address of the created pair. + */ function createPair(address tokenA, address tokenB) external returns (address pair); -} +} \ No newline at end of file diff --git a/contracts/helpers/IUniswapV2PairFull.sol b/contracts/helpers/IUniswapV2PairFull.sol index 847bae0..330e17c 100644 --- a/contracts/helpers/IUniswapV2PairFull.sol +++ b/contracts/helpers/IUniswapV2PairFull.sol @@ -5,53 +5,210 @@ */ pragma solidity 0.7.6; +/** + * @title IUniswapV2PairFull + * @dev Interface for a Uniswap V2 Pair with full functionality. + */ interface IUniswapV2PairFull { + // Events event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); + event Mint(address indexed sender, uint amount0, uint amount1); + event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); + event Swap( + address indexed sender, + uint amount0In, + uint amount1In, + uint amount0Out, + uint amount1Out, + address indexed to + ); + event Sync(uint112 reserve0, uint112 reserve1); + /** + * @dev Returns the name of the pair. + * @return The name of the pair. + */ function name() external pure returns (string memory); + + /** + * @dev Returns the symbol of the pair. + * @return The symbol of the pair. + */ function symbol() external pure returns (string memory); + + /** + * @dev Returns the number of decimals used to get its user representation. + * @return The number of decimals for the pair. + */ function decimals() external pure returns (uint8); + + /** + * @dev Returns the total supply of the liquidity tokens. + * @return The total supply. + */ function totalSupply() external view returns (uint); + + /** + * @dev Returns the amount of tokens owned by `owner`. + * @param owner The address of the token owner. + * @return The balance of the owner. + */ function balanceOf(address owner) external view returns (uint); + + /** + * @dev Returns the remaining number of tokens that `spender` is allowed to spend on behalf of `owner`. + * @param owner The address of the token owner. + * @param spender The address which is allowed to spend the tokens. + * @return The amount of tokens allowed to be spent. + */ function allowance(address owner, address spender) external view returns (uint); + /** + * @dev Approves `spender` to spend `value` tokens on behalf of the caller. + * @param spender The address which is allowed to spend the tokens. + * @param value The number of tokens to be spent. + * @return A boolean value indicating whether the operation succeeded. + */ function approve(address spender, uint value) external returns (bool); + + /** + * @dev Transfers `value` tokens to address `to`. + * @param to The address of the recipient. + * @param value The amount of tokens to be transferred. + * @return A boolean value indicating whether the operation succeeded. + */ function transfer(address to, uint value) external returns (bool); + + /** + * @dev Transfers `value` tokens from address `from` to address `to`. + * @param from The address of the sender. + * @param to The address of the recipient. + * @param value The amount of tokens to be transferred. + * @return A boolean value indicating whether the operation succeeded. + */ function transferFrom(address from, address to, uint value) external returns (bool); + /** + * @dev Returns the domain separator used in the encoding of the signature for `permit`, as defined by EIP-712. + * @return The domain separator. + */ function DOMAIN_SEPARATOR() external view returns (bytes32); + + /** + * @dev Returns the hash of the permit type used by the `permit` function. + * @return The permit typehash. + */ function PERMIT_TYPEHASH() external pure returns (bytes32); + + /** + * @dev Returns the current nonce for `owner`. This value must be included whenever a signature is generated for `permit`. + * @param owner The address whose nonce is being fetched. + * @return The nonce of the owner. + */ function nonces(address owner) external view returns (uint); + /** + * @dev Allows for the approval of `spender` to spend `value` tokens on behalf of `owner` via off-chain signatures. + * @param owner The address of the token owner. + * @param spender The address which is allowed to spend the tokens. + * @param value The number of tokens to be spent. + * @param deadline The time at which the permit is no longer valid. + * @param v The recovery byte of the signature. + * @param r Half of the ECDSA signature pair. + * @param s Half of the ECDSA signature pair. + */ function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; - event Mint(address indexed sender, uint amount0, uint amount1); - event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); - event Swap( - address indexed sender, - uint amount0In, - uint amount1In, - uint amount0Out, - uint amount1Out, - address indexed to - ); - event Sync(uint112 reserve0, uint112 reserve1); - + /** + * @dev Returns the minimum liquidity threshold for adding liquidity to the pool. + * @return The minimum liquidity threshold. + */ function MINIMUM_LIQUIDITY() external pure returns (uint); + + /** + * @dev Returns the factory address. + * @return The factory address. + */ function factory() external view returns (address); + + /** + * @dev Returns the address of the first token in the pair. + * @return The address of the first token. + */ function token0() external view returns (address); + + /** + * @dev Returns the address of the second token in the pair. + * @return The address of the second token. + */ function token1() external view returns (address); + + /** + * @dev Returns the reserves of token0 and token1 used to price trades and distribute liquidity. + * @return reserve0 The reserve of token0. + * @return reserve1 The reserve of token1. + * @return blockTimestampLast The last block timestamp when the reserves were updated. + */ function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); + + /** + * @dev Returns the last cumulative price of token0. + * @return The last cumulative price of token0. + */ function price0CumulativeLast() external view returns (uint); + + /** + * @dev Returns the last cumulative price of token1. + * @return The last cumulative price of token1. + */ function price1CumulativeLast() external view returns (uint); + + /** + * @dev Returns the value of the current liquidity threshold. + * @return The value of kLast. + */ function kLast() external view returns (uint); + /** + * @dev Adds liquidity to the pool and mints new LP tokens to `to`. + * @param to The address receiving the new liquidity tokens. + * @return liquidity The amount of liquidity tokens minted. + */ function mint(address to) external returns (uint liquidity); + + /** + * @dev Removes liquidity from the pool and burns LP tokens to withdraw the underlying assets. + * @param to The address receiving the underlying assets. + * @return amount0 The amount of the first token. + * @return amount1 The amount of the second token. + */ function burn(address to) external returns (uint amount0, uint amount1); + + /** + * @dev Executes a swap of `amount0Out` of token0 for `amount1Out` of token1, or vice versa. + * @param amount0Out The amount of token0 to be sent to `to`. + * @param amount1Out The amount of token1 to be sent to `to`. + * @param to The recipient address. + * @param data Additional data passed to the swap function, for use in callback. + */ function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; + + /** + * @dev Forces balances to match the reserves. + * @param to The address that receives the tokens. + */ function skim(address to) external; + + /** + * @dev Updates the reserves to match the current balances. + */ function sync() external; - function initialize(address, address) external; -} + /** + * @dev Initializes the pair with the provided token addresses. This is called by the factory contract. + * @param token0 The address of the first token. + * @param token1 The address of the second token. + */ + function initialize(address token0, address token1) external; +} \ No newline at end of file diff --git a/contracts/helpers/Math.sol b/contracts/helpers/Math.sol index 2f9c3b6..d1aab0d 100644 --- a/contracts/helpers/Math.sol +++ b/contracts/helpers/Math.sol @@ -5,36 +5,44 @@ */ pragma solidity 0.7.6; -/** +/* @title Math Library * @dev Standard math utilities missing in the Solidity language. */ library Math { - /** - * @dev Returns the largest of two numbers. + + /* @notice Calculate the maximum of two numbers + * @param a The first number to compare + * @param b The second number to compare + * @return The larger of two input numbers */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } - /** - * @dev Returns the smallest of two numbers. + /* @notice Calculate the minimum of two numbers + * @param a The first number to compare + * @param b The second number to compare + * @return The smaller of two input numbers */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } - /** - * @dev Returns the average of two numbers. The result is rounded towards - * zero. + /* @notice Calculate the average of two numbers, rounding towards zero + * @param a The first number + * @param b The second number + * @return The average of the two input numbers */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } - /** - * @dev babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) - **/ + /* @notice Calculate the square root of a number using the Babylonian method + * @dev See https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method + * @param x The number to calculate the square root of + * @return y The square root of the input number + */ function sqrt(uint x) internal pure returns (uint y) { if (x > 3) { uint z = x / 2 + 1; @@ -46,5 +54,6 @@ library Math { } else if (x != 0) { y = 1; } + // Note: if x is 0, y will be 0 (default value of uint) } -} +} \ No newline at end of file diff --git a/contracts/helpers/ReentrancyGuard.sol b/contracts/helpers/ReentrancyGuard.sol index 96736bf..ee1438c 100644 --- a/contracts/helpers/ReentrancyGuard.sol +++ b/contracts/helpers/ReentrancyGuard.sol @@ -2,7 +2,8 @@ pragma solidity 0.7.6; -/** +/* + * @title ReentrancyGuard * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier @@ -35,6 +36,9 @@ contract ReentrancyGuard { uint256 private _status; + /** + * @dev Initializes the contract by setting the `_status` variable to `_NOT_ENTERED`. + */ constructor () { _status = _NOT_ENTERED; } @@ -59,4 +63,4 @@ contract ReentrancyGuard { // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } -} +} \ No newline at end of file diff --git a/contracts/helpers/SafeMath.sol b/contracts/helpers/SafeMath.sol index 8bcafed..eec8fdf 100644 --- a/contracts/helpers/SafeMath.sol +++ b/contracts/helpers/SafeMath.sol @@ -5,16 +5,18 @@ */ pragma solidity 0.7.6; - -/** +/* * @title SafeMath - * @dev Math operations with safety checks that throw on error + * @dev Library for safe mathematical operations which prevents overflow and underflow. */ library SafeMath { - /** - * @dev Multiplies two numbers, throws on overflow. - */ + /* + * @dev Multiplies two numbers, reverts on overflow. + * @param a The first number as a uint256. + * @param b The second number as a uint256. + * @return c The product as a uint256. + */ function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { if (a == 0) { return 0; @@ -24,28 +26,37 @@ library SafeMath { return c; } - /** - * @dev Integer division of two numbers, truncating the quotient. - */ + /* + * @dev Divides one number by another, reverts on division by zero. + * @param a The dividend as a uint256. + * @param b The divisor as a uint256. + * @return The quotient as a uint256. + */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "SafeMath: division by zero"); return a / b; } - /** - * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). - */ + /* + * @dev Subtracts one number from another, reverts if the result would be negative. + * @param a The number to subtract from as a uint256. + * @param b The number to subtract as a uint256. + * @return The difference as a uint256. + */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } - /** - * @dev Adds two numbers, throws on overflow. - */ + /* + * @dev Adds two numbers, reverts on overflow. + * @param a The first number to add as a uint256. + * @param b The second number to add as a uint256. + * @return c The sum as a uint256. + */ function add(uint256 a, uint256 b) internal pure returns (uint256 c) { c = a + b; assert(c >= a); return c; } -} +} \ No newline at end of file diff --git a/contracts/helpers/TransferHelper.sol b/contracts/helpers/TransferHelper.sol index 3d867d3..81d35fc 100644 --- a/contracts/helpers/TransferHelper.sol +++ b/contracts/helpers/TransferHelper.sol @@ -5,28 +5,56 @@ */ pragma solidity 0.7.6; -// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false +/** + * @title TransferHelper + * @dev Library to provide safe methods for interacting with ERC20 tokens and sending ETH. + */ library TransferHelper { + + /** + * @dev Approves the `token` to spend `value` amount on behalf of the caller. + * @param token The address of the ERC20 token contract. + * @param to The address which will spend the funds. + * @param value The amount of tokens to be spent. + */ function safeApprove(address token, address to, uint value) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED'); } + /** + * @dev Transfers `value` amount of `token` to the address `to`. + * @param token The address of the ERC20 token contract. + * @param to The recipient address. + * @param value The amount of tokens to be transferred. + */ function safeTransfer(address token, address to, uint value) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED'); } + /** + * @dev Transfers `value` amount of `token` from the `from` address to the `to` address. + * @param token The address of the ERC20 token contract. + * @param from The address which you want to send tokens from. + * @param to The recipient address. + * @param value The amount of tokens to be transferred. + */ function safeTransferFrom(address token, address from, address to, uint value) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED'); } + /** + * @dev Transfers `value` amount of Ether to the address `to`. + * @param to The recipient address. + * @param value The amount of Ether to be transferred. + */ function safeTransferETH(address to, uint value) internal { (bool success,) = to.call{value:value}(new bytes(0)); require(success, 'TransferHelper: ETH_TRANSFER_FAILED'); } -} +} \ No newline at end of file diff --git a/contracts/interfaces/IAggregator.sol b/contracts/interfaces/IAggregator.sol index 01bc69a..c29bf2f 100644 --- a/contracts/interfaces/IAggregator.sol +++ b/contracts/interfaces/IAggregator.sol @@ -5,17 +5,58 @@ */ pragma solidity 0.7.6; - /** -**/ + * @title IAggregator + * @dev Interface for Chainlink or similar oracle aggregators to fetch price feed information. + */ interface IAggregator { + + /** + * @notice Retrieves the latest available answer from the oracle. + * @return The latest answer. + */ function latestAnswer() external view returns (int256); + + /** + * @notice Retrieves the timestamp of the latest update. + * @return Timestamp of the last update. + */ function latestTimestamp() external view returns (uint256); + + /** + * @notice Retrieves the identifier of the latest round. + * @return The latest round ID. + */ function latestRound() external view returns (uint256); + + /** + * @notice Fetches the historical answer for a specific round. + * @param roundId The round ID to retrieve the answer for. + * @return The answer of the specified round. + */ function getAnswer(uint256 roundId) external view returns (int256); + + /** + * @notice Fetches the timestamp when a specific round was updated. + * @param roundId The round ID to retrieve the timestamp for. + * @return The timestamp of the specified round. + */ function getTimestamp(uint256 roundId) external view returns (uint256); + + /** + * @notice Retrieves the number of decimals used by the oracle. + * @return The number of decimals. + */ function decimals() external view returns (uint256); - + + /** + * @notice Provides the round data including the answer and timestamps for the latest round. + * @return roundId The round ID of the latest round. + * @return answer The answer provided by the latest round. + * @return startedAt The timestamp at which the latest round started. + * @return updatedAt The timestamp at which the latest round was updated. + * @return answeredInRound The round ID in which the returned answer was computed. + */ function latestRoundData() external view @@ -27,6 +68,19 @@ interface IAggregator { uint80 answeredInRound ); + /** + * @dev Emitted when a new answer is provided by the oracle. + * @param current The value of the latest answer. + * @param roundId The round ID when the answer was updated. + * @param timestamp The timestamp when the answer was updated. + */ event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp); + + /** + * @dev Emitted when a new round is started. + * @param roundId The round ID that was started. + * @param startedBy The address that started the round. + * @param startedAt The timestamp at which the round was started. + */ event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); -} +} \ No newline at end of file diff --git a/contracts/interfaces/IBearingAssetOracle.sol b/contracts/interfaces/IBearingAssetOracle.sol index acb6022..75d9ad2 100644 --- a/contracts/interfaces/IBearingAssetOracle.sol +++ b/contracts/interfaces/IBearingAssetOracle.sol @@ -5,10 +5,45 @@ */ pragma solidity ^0.7.6; +/** + * @title IBearingAssetOracle + * @dev Interface for the bearing asset oracle which converts bearing asset amounts to USD and underlying assets. + */ interface IBearingAssetOracle { - function assetToUsd ( address bearing, uint256 amount ) external view returns ( uint256 ); - function bearingToUnderlying ( address bearing, uint256 amount ) external view returns ( address, uint256 ); - function oracleRegistry ( ) external view returns ( address ); - function setUnderlying ( address bearing, address underlying ) external; - function vaultParameters ( ) external view returns ( address ); -} + + /** + * @notice Convert the amount of the bearing asset to its equivalent in USD. + * @param bearing The address of the bearing asset. + * @param amount The amount of the bearing asset to convert. + * @return The equivalent amount in USD. + */ + function assetToUsd(address bearing, uint256 amount) external view returns (uint256); + + /** + * @notice Convert the amount of the bearing asset to its underlying asset and amount. + * @param bearing The address of the bearing asset. + * @param amount The amount of the bearing asset to convert. + * @return The address of the underlying asset and the equivalent amount of the underlying asset. + */ + function bearingToUnderlying(address bearing, uint256 amount) external view returns (address, uint256); + + /** + * @notice Get the address of the oracle registry. + * @return The address of the oracle registry. + */ + function oracleRegistry() external view returns (address); + + /** + * @notice Set the underlying asset for a given bearing asset. + * @dev This function can only be called by authorized entities. + * @param bearing The address of the bearing asset. + * @param underlying The address of the underlying asset to set. + */ + function setUnderlying(address bearing, address underlying) external; + + /** + * @notice Get the address of the vault parameters. + * @return The address of the vault parameters. + */ + function vaultParameters() external view returns (address); +} \ No newline at end of file diff --git a/contracts/interfaces/ICDPRegistry.sol b/contracts/interfaces/ICDPRegistry.sol index 66d8796..2f9517c 100644 --- a/contracts/interfaces/ICDPRegistry.sol +++ b/contracts/interfaces/ICDPRegistry.sol @@ -6,23 +6,101 @@ pragma solidity ^0.7.6; pragma experimental ABIEncoderV2; +/** + * @title ICDPRegistry + * @dev Interface for CDPRegistry, a contract that manages the registry of Collateralized Debt Positions (CDPs). + */ interface ICDPRegistry { + /** + * @dev Represents a collateralized debt position (CDP). + * @param asset The address of the collateral asset. + * @param owner The address of the owner of the CDP. + */ struct CDP { address asset; address owner; } - function batchCheckpoint ( address[] calldata assets, address[] calldata owners ) external; - function batchCheckpointForAsset ( address asset, address[] calldata owners ) external; - function checkpoint ( address asset, address owner ) external; - function cr ( ) external view returns ( address ); - function getAllCdps ( ) external view returns ( CDP[] memory r ); - function getCdpsByCollateral ( address asset ) external view returns ( CDP[] memory cdps ); - function getCdpsByOwner ( address owner ) external view returns ( CDP[] memory r ); - function getCdpsCount ( ) external view returns ( uint256 totalCdpCount ); - function getCdpsCountForCollateral ( address asset ) external view returns ( uint256 ); - function isAlive ( address asset, address owner ) external view returns ( bool ); - function isListed ( address asset, address owner ) external view returns ( bool ); - function vault ( ) external view returns ( address ); -} + /** + * @dev Registers a batch checkpoint for multiple CDPs. + * @param assets Array of asset addresses corresponding to the CDPs. + * @param owners Array of owner addresses corresponding to the CDPs. + */ + function batchCheckpoint(address[] calldata assets, address[] calldata owners) external; + + /** + * @dev Registers a batch checkpoint for a single asset and multiple owners. + * @param asset The address of the asset for which to checkpoint. + * @param owners Array of owner addresses corresponding to the CDPs. + */ + function batchCheckpointForAsset(address asset, address[] calldata owners) external; + + /** + * @dev Registers a checkpoint for a single CDP. + * @param asset The address of the collateral asset. + * @param owner The address of the owner of the CDP. + */ + function checkpoint(address asset, address owner) external; + + /** + * @dev Returns the address of the Collateral Ratio contract. + * @return The address of the CR contract. + */ + function cr() external view returns (address); + + /** + * @dev Retrieves all CDPs in the registry. + * @return r An array of all CDPs. + */ + function getAllCdps() external view returns (CDP[] memory r); + + /** + * @dev Retrieves all CDPs associated with a particular collateral asset. + * @param asset The address of the collateral asset. + * @return cdps An array of CDPs for the specified asset. + */ + function getCdpsByCollateral(address asset) external view returns (CDP[] memory cdps); + + /** + * @dev Retrieves all CDPs associated with a particular owner. + * @param owner The address of the owner. + * @return r An array of CDPs for the specified owner. + */ + function getCdpsByOwner(address owner) external view returns (CDP[] memory r); + + /** + * @dev Returns the total count of CDPs in the registry. + * @return totalCdpCount The total number of CDPs. + */ + function getCdpsCount() external view returns (uint256 totalCdpCount); + + /** + * @dev Returns the count of CDPs for a given collateral asset. + * @param asset The address of the collateral asset. + * @return The number of CDPs for the specified asset. + */ + function getCdpsCountForCollateral(address asset) external view returns (uint256); + + /** + * @dev Checks if a CDP is alive (active and not closed). + * @param asset The address of the collateral asset. + * @param owner The address of the owner of the CDP. + * @return True if the CDP is alive, false otherwise. + */ + function isAlive(address asset, address owner) external view returns (bool); + + /** + * @dev Checks if a CDP is listed in the registry. + * @param asset The address of the collateral asset. + * @param owner The address of the owner of the CDP. + * @return True if the CDP is listed, false otherwise. + */ + function isListed(address asset, address owner) external view returns (bool); + + /** + * @dev Returns the address of the vault contract. + * @return The address of the vault contract. + */ + function vault() external view returns (address); +} \ No newline at end of file diff --git a/contracts/interfaces/ICollateralRegistry.sol b/contracts/interfaces/ICollateralRegistry.sol index 3b7d6d9..c1e5357 100644 --- a/contracts/interfaces/ICollateralRegistry.sol +++ b/contracts/interfaces/ICollateralRegistry.sol @@ -5,13 +5,60 @@ */ pragma solidity ^0.7.6; +/** + * @title ICollateralRegistry + * @dev Interface for the management of collateral assets within the system. + */ interface ICollateralRegistry { - function addCollateral ( address asset ) external; - function collateralId ( address ) external view returns ( uint256 ); - function collaterals ( ) external view returns ( address[] memory ); - function removeCollateral ( address asset ) external; - function vaultParameters ( ) external view returns ( address ); - function isCollateral ( address asset ) external view returns ( bool ); - function collateralList ( uint id ) external view returns ( address ); - function collateralsCount ( ) external view returns ( uint ); -} + + /** + * @dev Adds a new collateral asset to the registry. + * @param asset The address of the collateral asset to add. + */ + function addCollateral(address asset) external; + + /** + * @dev Retrieves the ID of a collateral asset. + * @param asset The address of the collateral asset. + * @return The ID of the collateral asset. + */ + function collateralId(address asset) external view returns (uint256); + + /** + * @dev Retrieves the list of all collateral assets in the registry. + * @return An array of addresses of the collateral assets. + */ + function collaterals() external view returns (address[] memory); + + /** + * @dev Removes a collateral asset from the registry. + * @param asset The address of the collateral asset to remove. + */ + function removeCollateral(address asset) external; + + /** + * @dev Retrieves the address of the VaultParameters contract. + * @return The address of the VaultParameters contract. + */ + function vaultParameters() external view returns (address); + + /** + * @dev Checks if an address is a collateral in the registry. + * @param asset The address of the collateral asset to check. + * @return True if the address is a collateral, false otherwise. + */ + function isCollateral(address asset) external view returns (bool); + + /** + * @dev Retrieves the address of a collateral by its ID. + * @param id The ID of the collateral asset. + * @return The address of the collateral asset. + */ + function collateralList(uint id) external view returns (address); + + /** + * @dev Retrieves the count of collateral assets in the registry. + * @return The count of collateral assets. + */ + function collateralsCount() external view returns (uint); +} \ No newline at end of file diff --git a/contracts/interfaces/ICurvePool.sol b/contracts/interfaces/ICurvePool.sol index e6325cd..853b447 100644 --- a/contracts/interfaces/ICurvePool.sol +++ b/contracts/interfaces/ICurvePool.sol @@ -5,7 +5,22 @@ */ pragma solidity ^0.7.6; +/** + * @title ICurvePool + * @dev Interface for interacting with Curve.fi pools + */ interface ICurvePool { + + /** + * @dev Get the virtual price, which is the value of 1 LP token in the underlying stablecoins + * @return uint The current virtual price + */ function get_virtual_price() external view returns (uint); - function coins(uint) external view returns (address); + + /** + * @dev Get the address of the specified coin in the pool + * @param index The index of the coin to retrieve + * @return address The address of the coin at the specified index + */ + function coins(uint index) external view returns (address); } \ No newline at end of file diff --git a/contracts/interfaces/ICurveProvider.sol b/contracts/interfaces/ICurveProvider.sol index a92a8e9..abda7ac 100644 --- a/contracts/interfaces/ICurveProvider.sol +++ b/contracts/interfaces/ICurveProvider.sol @@ -5,6 +5,14 @@ */ pragma solidity ^0.7.6; +/** + * @title ICurveProvider + * @dev Interface for interacting with the Curve protocol's provider contract. + */ interface ICurveProvider { + /** + * @dev Returns the address of the Curve registry contract. + * @return The address of the Curve registry. + */ function get_registry() external view returns (address); } \ No newline at end of file diff --git a/contracts/interfaces/ICurveRegistry.sol b/contracts/interfaces/ICurveRegistry.sol index 931d6de..b225770 100644 --- a/contracts/interfaces/ICurveRegistry.sol +++ b/contracts/interfaces/ICurveRegistry.sol @@ -5,7 +5,23 @@ */ pragma solidity ^0.7.6; +/** + * @title ICurveRegistry + * @dev Interface for interacting with the Curve Registry to fetch pool information. + */ interface ICurveRegistry { - function get_pool_from_lp_token(address) external view returns (address); - function get_n_coins(address) external view returns (uint[2] memory); + + /** + * @dev Given an LP token address, returns the corresponding Curve pool address. + * @param lpToken The address of the liquidity provider token. + * @return The address of the Curve pool. + */ + function get_pool_from_lp_token(address lpToken) external view returns (address); + + /** + * @dev Given a Curve pool address, returns the number of coins the pool supports. + * @param pool The address of the Curve pool. + * @return An array where the first element is the number of coins in the pool, and the second element is 0. + */ + function get_n_coins(address pool) external view returns (uint[2] memory); } \ No newline at end of file diff --git a/contracts/interfaces/IERC20WithOptional.sol b/contracts/interfaces/IERC20WithOptional.sol index d97c7f6..9fd1463 100644 --- a/contracts/interfaces/IERC20WithOptional.sol +++ b/contracts/interfaces/IERC20WithOptional.sol @@ -7,8 +7,26 @@ pragma solidity ^0.7.6; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +/** + * @title Interface for ERC20 tokens with optional metadata functions + * @dev Extends IERC20 to include optional metadata functions + */ interface IERC20WithOptional is IERC20 { + /** + * @dev Returns the name of the token. + * @return The token name. + */ function name() external view returns (string memory); + + /** + * @dev Returns the symbol of the token. + * @return The token symbol. + */ function symbol() external view returns (string memory); + + /** + * @dev Returns the number of decimals the token uses. + * @return The number of decimals for getting user representation of a token amount. + */ function decimals() external view returns (uint8); -} +} \ No newline at end of file diff --git a/contracts/interfaces/IFoundation.sol b/contracts/interfaces/IFoundation.sol index 42d5649..bdf47a8 100644 --- a/contracts/interfaces/IFoundation.sol +++ b/contracts/interfaces/IFoundation.sol @@ -2,6 +2,15 @@ pragma solidity ^0.7.6; +/** + * @title Interface for Foundation contract + * @dev This interface declares a function for submitting liquidation fees. + */ interface IFoundation { + + /** + * @dev Submits a liquidation fee to the Foundation. + * @param fee The amount of the liquidation fee to submit. + */ function submitLiquidationFee(uint fee) external; -} +} \ No newline at end of file diff --git a/contracts/interfaces/IOracleEth.sol b/contracts/interfaces/IOracleEth.sol index d70d51b..ad6161f 100644 --- a/contracts/interfaces/IOracleEth.sol +++ b/contracts/interfaces/IOracleEth.sol @@ -5,15 +5,32 @@ */ pragma solidity ^0.7.6; +/** + * @title IOracleEth + * @dev Interface for the ETH-based price oracle, providing conversion rates between assets and ETH, and ETH to USD. + */ interface IOracleEth { - // returns Q112-encoded value - // returned value 10**18 * 2**112 is 1 Ether + /** + * @dev Returns the Q112-encoded value of the asset in terms of ETH. + * @param asset The address of the asset token contract. + * @param amount The amount of the asset tokens to convert. + * @return The equivalent amount of asset in ETH, encoded in Q112 format. + * @notice The returned value scaled by 10**18 * 2**112 represents 1 Ether. + */ function assetToEth(address asset, uint amount) external view returns (uint); - // returns the value "as is" + /** + * @dev Returns the value of ETH in terms of USD. + * @param amount The amount of ETH to convert. + * @return The equivalent amount of ETH in USD, without any encoding. + */ function ethToUsd(uint amount) external view returns (uint); - // returns the value "as is" + /** + * @dev Returns the value of USD in terms of ETH. + * @param amount The amount of USD to convert. + * @return The equivalent amount of USD in ETH, without any encoding. + */ function usdToEth(uint amount) external view returns (uint); } \ No newline at end of file diff --git a/contracts/interfaces/IOracleRegistry.sol b/contracts/interfaces/IOracleRegistry.sol index 8d6d23a..1af21a2 100644 --- a/contracts/interfaces/IOracleRegistry.sol +++ b/contracts/interfaces/IOracleRegistry.sol @@ -6,28 +6,127 @@ pragma solidity ^0.7.6; pragma abicoder v2; +/** + * @title IOracleRegistry + * @dev Interface for the Oracle Registry which manages oracles and their types. + */ interface IOracleRegistry { + /** + * @dev Represents an Oracle with its type and address. + */ struct Oracle { - uint oracleType; - address oracleAddress; + uint oracleType; // The type of the oracle + address oracleAddress; // The address of the oracle } - function WETH ( ) external view returns ( address ); - function getKeydonixOracleTypes ( ) external view returns ( uint256[] memory ); - function getOracles ( ) external view returns ( Oracle[] memory foundOracles ); - function keydonixOracleTypes ( uint256 ) external view returns ( uint256 ); - function maxOracleType ( ) external view returns ( uint256 ); - function oracleByAsset ( address asset ) external view returns ( address ); - function oracleByType ( uint256 ) external view returns ( address ); - function oracleTypeByAsset ( address ) external view returns ( uint256 ); - function oracleTypeByOracle ( address ) external view returns ( uint256 ); - function setKeydonixOracleTypes ( uint256[] memory _keydonixOracleTypes ) external; - function setOracle ( uint256 oracleType, address oracle ) external; - function setOracleTypeForAsset ( address asset, uint256 oracleType ) external; - function setOracleTypeForAssets ( address[] memory assets, uint256 oracleType ) external; - function unsetOracle ( uint256 oracleType ) external; - function unsetOracleForAsset ( address asset ) external; - function unsetOracleForAssets ( address[] memory assets ) external; - function vaultParameters ( ) external view returns ( address ); -} + /** + * @dev Returns the address of WETH token. + * @return The WETH token address. + */ + function WETH() external view returns (address); + + /** + * @dev Returns an array of Keydonix oracle types. + * @return An array of Keydonix oracle types. + */ + function getKeydonixOracleTypes() external view returns (uint256[] memory); + + /** + * @dev Returns an array of all oracles with their types. + * @return foundOracles An array of Oracle struct containing oracle types and addresses. + */ + function getOracles() external view returns (Oracle[] memory foundOracles); + + /** + * @dev Returns a Keydonix oracle type by its index. + * @param index The index of the Keydonix oracle type. + * @return The Keydonix oracle type. + */ + function keydonixOracleTypes(uint256 index) external view returns (uint256); + + /** + * @dev Returns the maximum oracle type value. + * @return The maximum oracle type value. + */ + function maxOracleType() external view returns (uint256); + + /** + * @dev Returns the oracle address for a given asset. + * @param asset The address of the asset. + * @return The oracle address. + */ + function oracleByAsset(address asset) external view returns (address); + + /** + * @dev Returns the oracle address for a given oracle type. + * @param oracleType The oracle type. + * @return The oracle address. + */ + function oracleByType(uint256 oracleType) external view returns (address); + + /** + * @dev Returns the oracle type for a given asset. + * @param asset The address of the asset. + * @return The oracle type. + */ + function oracleTypeByAsset(address asset) external view returns (uint256); + + /** + * @dev Returns the oracle type for a given oracle address. + * @param oracle The address of the oracle. + * @return The oracle type. + */ + function oracleTypeByOracle(address oracle) external view returns (uint256); + + /** + * @dev Sets the Keydonix oracle types. + * @param _keydonixOracleTypes An array of new Keydonix oracle types. + */ + function setKeydonixOracleTypes(uint256[] memory _keydonixOracleTypes) external; + + /** + * @dev Sets an oracle with its type. + * @param oracleType The oracle type. + * @param oracle The oracle address. + */ + function setOracle(uint256 oracleType, address oracle) external; + + /** + * @dev Sets the oracle type for an asset. + * @param asset The asset address. + * @param oracleType The oracle type. + */ + function setOracleTypeForAsset(address asset, uint256 oracleType) external; + + /** + * @dev Sets the same oracle type for multiple assets. + * @param assets An array of asset addresses. + * @param oracleType The oracle type. + */ + function setOracleTypeForAssets(address[] memory assets, uint256 oracleType) external; + + /** + * @dev Unsets the oracle for a given oracle type. + * @param oracleType The oracle type. + */ + function unsetOracle(uint256 oracleType) external; + + /** + * @dev Unsets the oracle for a given asset. + * @param asset The asset address. + */ + function unsetOracleForAsset(address asset) external; + + /** + * @dev Unsets the oracles for multiple assets. + * @param assets An array of asset addresses. + */ + function unsetOracleForAssets(address[] memory assets) external; + + /** + * @dev Returns the address of the vault parameters contract. + * @return The address of the vault parameters contract. + */ + function vaultParameters() external view returns (address); +} \ No newline at end of file diff --git a/contracts/interfaces/IOracleUsd.sol b/contracts/interfaces/IOracleUsd.sol index 246112c..41cd2f4 100644 --- a/contracts/interfaces/IOracleUsd.sol +++ b/contracts/interfaces/IOracleUsd.sol @@ -5,9 +5,17 @@ */ pragma solidity ^0.7.6; +/** + * @title IOracleUsd + * @dev Interface for Oracle that provides USD price for an asset. + */ interface IOracleUsd { - // returns Q112-encoded value - // returned value 10**18 * 2**112 is $1 + /** + * @notice Converts asset amount to USD price. + * @param asset The address of the asset. + * @param amount The amount of the asset to convert. + * @return The USD price of the given asset amount, encoded in Q112 format (10**18 * 2**112 is $1). + */ function assetToUsd(address asset, uint amount) external view returns (uint); } \ No newline at end of file diff --git a/contracts/interfaces/IStETH.sol b/contracts/interfaces/IStETH.sol index ae6e071..e69c0f1 100644 --- a/contracts/interfaces/IStETH.sol +++ b/contracts/interfaces/IStETH.sol @@ -5,6 +5,15 @@ */ pragma solidity ^0.7.6; -interface IStETH { +/** + * @title Interface for the StETH contract + */ +interface IStETH { + + /** + * @notice Calculate the amount of Ether pooled for the given amount of shares + * @param _sharesAmount The amount of shares + * @return The amount of pooled Ether + */ function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256); -} +} \ No newline at end of file diff --git a/contracts/interfaces/IStEthPriceFeed.sol b/contracts/interfaces/IStEthPriceFeed.sol index d37d93c..8aee29d 100644 --- a/contracts/interfaces/IStEthPriceFeed.sol +++ b/contracts/interfaces/IStEthPriceFeed.sol @@ -5,7 +5,26 @@ */ pragma solidity ^0.7.6; +/** + * @title Interface for StEth Price Feed + * @dev Interface to interact with the StEth price feed oracle. + */ interface IStEthPriceFeed { + + /** + * @notice Get the current price of StEth. + * @dev Returns the latest price of StEth. + * @return uint256 The current price. + * @return bool True if the current price is valid, false if invalid. + */ function current_price() external view returns (uint256,bool); + + /** + * @notice Get detailed price information of StEth. + * @dev Returns the full price information including the price, validity, and timestamp. + * @return uint256 The current price. + * @return bool True if the current price is valid, false if invalid. + * @return uint256 The timestamp of the last price update. + */ function full_price_info() external view returns (uint256,bool,uint256); -} +} \ No newline at end of file diff --git a/contracts/interfaces/IStableSwap.sol b/contracts/interfaces/IStableSwap.sol index b86535a..760b2ed 100644 --- a/contracts/interfaces/IStableSwap.sol +++ b/contracts/interfaces/IStableSwap.sol @@ -5,6 +5,18 @@ */ pragma solidity ^0.7.6; -interface IStableSwap { - function get_dy(uint256 x, uint256 y, uint256 dx) external view returns (uint256); -} +/** + * @title IStableSwap Interface + * @dev Interface for the StableSwap contract. + */ +interface IStableSwap { + + /** + * @notice Calculate the amount of token y you receive for token x with an amount of dx + * @param x The index of the token being sold + * @param y The index of the token being bought + * @param dx The amount of token x being sold + * @return The amount of token y that will be received + */ + function get_dy(uint256 x, uint256 y, uint256 dx) external view returns (uint256); +} \ No newline at end of file diff --git a/contracts/interfaces/IStableSwapStateOracle.sol b/contracts/interfaces/IStableSwapStateOracle.sol index 0de8d79..f59c1bd 100644 --- a/contracts/interfaces/IStableSwapStateOracle.sol +++ b/contracts/interfaces/IStableSwapStateOracle.sol @@ -5,6 +5,15 @@ */ pragma solidity ^0.7.6; -interface IStableSwapStateOracle { +/** + * @title IStableSwapStateOracle Interface + * @dev Interface for a contract that provides the price of stETH token. + */ +interface IStableSwapStateOracle { + + /** + * @dev Returns the current price of stETH token + * @return The price of stETH + */ function stethPrice() external view returns (uint256); -} +} \ No newline at end of file diff --git a/contracts/interfaces/IToken.sol b/contracts/interfaces/IToken.sol index f3718e5..01066dd 100644 --- a/contracts/interfaces/IToken.sol +++ b/contracts/interfaces/IToken.sol @@ -5,6 +5,20 @@ */ pragma solidity ^0.7.6; +/** + * @title IToken + * @dev Interface for a token contract, providing a decimals function. + */ interface IToken { + /** + * @dev Returns the number of decimals used to get its user representation. + * For example, if `decimals` equals `2`, a balance of `505` tokens should + * be displayed to a user as `5.05` (`505 / 10 ** 2`). + * + * Tokens usually opt for a value of 18, imitating the relationship between + * Ether and Wei. + * + * @return uint8 The number of decimals in use by the token. + */ function decimals() external view returns (uint8); } \ No newline at end of file diff --git a/contracts/interfaces/IVault.sol b/contracts/interfaces/IVault.sol index e3601f4..79e9043 100644 --- a/contracts/interfaces/IVault.sol +++ b/contracts/interfaces/IVault.sol @@ -5,38 +5,273 @@ */ pragma solidity ^0.7.6; +/** + * @title IVault + * @dev Interface for the Vault contract in Unit Protocol. + */ interface IVault { - function DENOMINATOR_1E2 ( ) external view returns ( uint256 ); - function DENOMINATOR_1E5 ( ) external view returns ( uint256 ); - function borrow ( address asset, address user, uint256 amount ) external returns ( uint256 ); - function calculateFee ( address asset, address user, uint256 amount ) external view returns ( uint256 ); - function changeOracleType ( address asset, address user, uint256 newOracleType ) external; - function chargeFee ( address asset, address user, uint256 amount ) external; - function col ( ) external view returns ( address ); - function colToken ( address, address ) external view returns ( uint256 ); - function collaterals ( address, address ) external view returns ( uint256 ); - function debts ( address, address ) external view returns ( uint256 ); - function depositCol ( address asset, address user, uint256 amount ) external; - function depositEth ( address user ) external payable; - function depositMain ( address asset, address user, uint256 amount ) external; - function destroy ( address asset, address user ) external; - function getTotalDebt ( address asset, address user ) external view returns ( uint256 ); - function lastUpdate ( address, address ) external view returns ( uint256 ); - function liquidate ( address asset, address positionOwner, uint256 mainAssetToLiquidator, uint256 colToLiquidator, uint256 mainAssetToPositionOwner, uint256 colToPositionOwner, uint256 repayment, uint256 penalty, address liquidator ) external; - function liquidationBlock ( address, address ) external view returns ( uint256 ); - function liquidationFee ( address, address ) external view returns ( uint256 ); - function liquidationPrice ( address, address ) external view returns ( uint256 ); - function oracleType ( address, address ) external view returns ( uint256 ); - function repay ( address asset, address user, uint256 amount ) external returns ( uint256 ); - function spawn ( address asset, address user, uint256 _oracleType ) external; - function stabilityFee ( address, address ) external view returns ( uint256 ); - function tokenDebts ( address ) external view returns ( uint256 ); - function triggerLiquidation ( address asset, address positionOwner, uint256 initialPrice ) external; - function update ( address asset, address user ) external; - function usdp ( ) external view returns ( address ); - function vaultParameters ( ) external view returns ( address ); - function weth ( ) external view returns ( address payable ); - function withdrawCol ( address asset, address user, uint256 amount ) external; - function withdrawEth ( address user, uint256 amount ) external; - function withdrawMain ( address asset, address user, uint256 amount ) external; -} + /** + * @dev Returns the denominator for calculations with precision to 2 decimal places. + * @return The denominator for percentage calculations. + */ + function DENOMINATOR_1E2() external view returns (uint256); + + /** + * @dev Returns the denominator for calculations with precision to 5 decimal places. + * @return The denominator for high precision calculations. + */ + function DENOMINATOR_1E5() external view returns (uint256); + + /** + * @dev Allows users to borrow specified amount of asset. + * @param asset The address of the asset to borrow. + * @param user The address of the user borrowing the asset. + * @param amount The amount of the asset to borrow. + * @return The actual amount borrowed. + */ + function borrow(address asset, address user, uint256 amount) external returns (uint256); + + /** + * @dev Calculates the fee for borrowing. + * @param asset The address of the borrowed asset. + * @param user The address of the user that borrowed the asset. + * @param amount The amount of the asset borrowed. + * @return The fee associated with the borrowing. + */ + function calculateFee(address asset, address user, uint256 amount) external view returns (uint256); + + /** + * @dev Changes the oracle type for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @param newOracleType The new oracle type identifier. + */ + function changeOracleType(address asset, address user, uint256 newOracleType) external; + + /** + * @dev Charges the fee for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @param amount The amount to be charged as fee. + */ + function chargeFee(address asset, address user, uint256 amount) external; + + /** + * @dev Returns the address of the collateral token. + * @return The address of the collateral token. + */ + function col() external view returns (address); + + /** + * @dev Returns the amount of collateral token for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The amount of collateral token. + */ + function colToken(address asset, address user) external view returns (uint256); + + /** + * @dev Returns the amount of collateral for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The amount of collateral. + */ + function collaterals(address asset, address user) external view returns (uint256); + + /** + * @dev Returns the debt of a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The debt amount. + */ + function debts(address asset, address user) external view returns (uint256); + + /** + * @dev Allows users to deposit collateral token. + * @param asset The address of the asset. + * @param user The address of the user depositing collateral. + * @param amount The amount of collateral to deposit. + */ + function depositCol(address asset, address user, uint256 amount) external; + + /** + * @dev Allows users to deposit ETH as collateral. + * @param user The address of the user depositing ETH. + */ + function depositEth(address user) external payable; + + /** + * @dev Allows users to deposit main collateral token. + * @param asset The address of the asset. + * @param user The address of the user depositing collateral. + * @param amount The amount of main collateral token to deposit. + */ + function depositMain(address asset, address user, uint256 amount) external; + + /** + * @dev Destroys the position for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + */ + function destroy(address asset, address user) external; + + /** + * @dev Returns the total debt for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The total debt amount. + */ + function getTotalDebt(address asset, address user) external view returns (uint256); + + /** + * @dev Returns the timestamp of the last update for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The timestamp of the last update. + */ + function lastUpdate(address asset, address user) external view returns (uint256); + + /** + * @dev Liquidates a position. + * @param asset The address of the asset. + * @param positionOwner The address of the position owner. + * @param mainAssetToLiquidator The amount of main asset to be sent to the liquidator. + * @param colToLiquidator The amount of collateral to be sent to the liquidator. + * @param mainAssetToPositionOwner The amount of main asset to be returned to the position owner. + * @param colToPositionOwner The amount of collateral to be returned to the position owner. + * @param repayment The amount of debt to be repaid. + * @param penalty The penalty fee for liquidation. + * @param liquidator The address of the liquidator. + */ + function liquidate( + address asset, + address positionOwner, + uint256 mainAssetToLiquidator, + uint256 colToLiquidator, + uint256 mainAssetToPositionOwner, + uint256 colToPositionOwner, + uint256 repayment, + uint256 penalty, + address liquidator + ) external; + + /** + * @dev Returns the block number when liquidation was triggered for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The block number of the liquidation trigger. + */ + function liquidationBlock(address asset, address user) external view returns (uint256); + + /** + * @dev Returns the liquidation fee for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The liquidation fee amount. + */ + function liquidationFee(address asset, address user) external view returns (uint256); + + /** + * @dev Returns the liquidation price for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The liquidation price. + */ + function liquidationPrice(address asset, address user) external view returns (uint256); + + /** + * @dev Returns the oracle type for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The oracle type identifier. + */ + function oracleType(address asset, address user) external view returns (uint256); + + /** + * @dev Allows users to repay part of the debt. + * @param asset The address of the asset. + * @param user The address of the user repaying the debt. + * @param amount The amount to be repaid. + * @return The actual amount repaid. + */ + function repay(address asset, address user, uint256 amount) external returns (uint256); + + /** + * @dev Creates a new position for a given asset and user with a specific oracle type. + * @param asset The address of the asset. + * @param user The address of the user spawning the position. + * @param _oracleType The oracle type identifier. + */ + function spawn(address asset, address user, uint256 _oracleType) external; + + /** + * @dev Returns the stability fee for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + * @return The stability fee amount. + */ + function stabilityFee(address asset, address user) external view returns (uint256); + + /** + * @dev Returns the total token debt for a given asset. + * @param asset The address of the asset. + * @return The total token debt. + */ + function tokenDebts(address asset) external view returns (uint256); + + /** + * @dev Triggers liquidation for a given asset and user at an initial price. + * @param asset The address of the asset. + * @param positionOwner The address of the position owner. + * @param initialPrice The initial price for liquidation. + */ + function triggerLiquidation(address asset, address positionOwner, uint256 initialPrice) external; + + /** + * @dev Updates the position for a given asset and user. + * @param asset The address of the asset. + * @param user The address of the user. + */ + function update(address asset, address user) external; + + /** + * @dev Returns the address of the USD pegged token. + * @return The address of the USD pegged token. + */ + function usdp() external view returns (address); + + /** + * @dev Returns the address of the vault parameters contract. + * @return The address of the vault parameters contract. + */ + function vaultParameters() external view returns (address); + + /** + * @dev Returns the address of the wrapped ETH token. + * @return The address of the wrapped ETH token. + */ + function weth() external view returns (address payable); + + /** + * @dev Allows users to withdraw collateral token. + * @param asset The address of the asset. + * @param user The address of the user withdrawing collateral. + * @param amount The amount of collateral to withdraw. + */ + function withdrawCol(address asset, address user, uint256 amount) external; + + /** + * @dev Allows users to withdraw ETH. + * @param user The address of the user withdrawing ETH. + * @param amount The amount of ETH to withdraw. + */ + function withdrawEth(address user, uint256 amount) external; + + /** + * @dev Allows users to withdraw main collateral token. + * @param asset The address of the asset. + * @param user The address of the user withdrawing collateral. + * @param amount The amount of main collateral token to withdraw. + */ + function withdrawMain(address asset, address user, uint256 amount) external; +} \ No newline at end of file diff --git a/contracts/interfaces/IVaultParameters.sol b/contracts/interfaces/IVaultParameters.sol index 264369a..3ba42e6 100644 --- a/contracts/interfaces/IVaultParameters.sol +++ b/contracts/interfaces/IVaultParameters.sol @@ -5,22 +5,129 @@ */ pragma solidity ^0.7.6; +/** + * @title IVaultParameters + * @dev Interface for interacting with Vault parameters. + */ interface IVaultParameters { - function canModifyVault ( address ) external view returns ( bool ); - function foundation ( ) external view returns ( address ); - function isManager ( address ) external view returns ( bool ); - function isOracleTypeEnabled ( uint256, address ) external view returns ( bool ); - function liquidationFee ( address ) external view returns ( uint256 ); - function setCollateral ( address asset, uint256 stabilityFeeValue, uint256 liquidationFeeValue, uint256 usdpLimit, uint256[] calldata oracles ) external; - function setFoundation ( address newFoundation ) external; - function setLiquidationFee ( address asset, uint256 newValue ) external; - function setManager ( address who, bool permit ) external; - function setOracleType ( uint256 _type, address asset, bool enabled ) external; - function setStabilityFee ( address asset, uint256 newValue ) external; - function setTokenDebtLimit ( address asset, uint256 limit ) external; - function setVaultAccess ( address who, bool permit ) external; - function stabilityFee ( address ) external view returns ( uint256 ); - function tokenDebtLimit ( address ) external view returns ( uint256 ); - function vault ( ) external view returns ( address ); - function vaultParameters ( ) external view returns ( address ); -} + + /** + * @notice Check if an address has permission to modify the vault. + * @param who The address to check. + * @return True if the address has modification permissions, false otherwise. + */ + function canModifyVault(address who) external view returns (bool); + + /** + * @notice Get the foundation address. + * @return The foundation address. + */ + function foundation() external view returns (address); + + /** + * @notice Check if an address is a manager. + * @param who The address to check. + * @return True if the address is a manager, false otherwise. + */ + function isManager(address who) external view returns (bool); + + /** + * @notice Check if an oracle type is enabled for a specific asset. + * @param _type The oracle type identifier. + * @param asset The address of the asset. + * @return True if the oracle type is enabled, false otherwise. + */ + function isOracleTypeEnabled(uint256 _type, address asset) external view returns (bool); + + /** + * @notice Get the liquidation fee for a specific asset. + * @param asset The address of the asset. + * @return The liquidation fee as a percentage. + */ + function liquidationFee(address asset) external view returns (uint256); + + /** + * @notice Set collateral parameters for a specific asset. + * @param asset The address of the asset. + * @param stabilityFeeValue The stability fee as a percentage. + * @param liquidationFeeValue The liquidation fee as a percentage. + * @param usdpLimit The USDP limit for the asset. + * @param oracles The array of oracle addresses. + */ + function setCollateral(address asset, uint256 stabilityFeeValue, uint256 liquidationFeeValue, uint256 usdpLimit, uint256[] calldata oracles) external; + + /** + * @notice Set the foundation address. + * @param newFoundation The new foundation address. + */ + function setFoundation(address newFoundation) external; + + /** + * @notice Set the liquidation fee for a specific asset. + * @param asset The address of the asset. + * @param newValue The new liquidation fee as a percentage. + */ + function setLiquidationFee(address asset, uint256 newValue) external; + + /** + * @notice Set or unset an address as a manager. + * @param who The address to set or unset as a manager. + * @param permit True to set as a manager, false to unset. + */ + function setManager(address who, bool permit) external; + + /** + * @notice Enable or disable an oracle type for a specific asset. + * @param _type The oracle type identifier. + * @param asset The address of the asset. + * @param enabled True to enable, false to disable the oracle type. + */ + function setOracleType(uint256 _type, address asset, bool enabled) external; + + /** + * @notice Set the stability fee for a specific asset. + * @param asset The address of the asset. + * @param newValue The new stability fee as a percentage. + */ + function setStabilityFee(address asset, uint256 newValue) external; + + /** + * @notice Set the token debt limit for a specific asset. + * @param asset The address of the asset. + * @param limit The new debt limit. + */ + function setTokenDebtLimit(address asset, uint256 limit) external; + + /** + * @notice Set or unset vault access for an address. + * @param who The address to set or unset vault access. + * @param permit True to set access, false to unset. + */ + function setVaultAccess(address who, bool permit) external; + + /** + * @notice Get the stability fee for a specific asset. + * @param asset The address of the asset. + * @return The stability fee as a percentage. + */ + function stabilityFee(address asset) external view returns (uint256); + + /** + * @notice Get the token debt limit for a specific asset. + * @param asset The address of the asset. + * @return The debt limit. + */ + function tokenDebtLimit(address asset) external view returns (uint256); + + /** + * @notice Get the vault address. + * @return The vault address. + */ + function vault() external view returns (address); + + /** + * @notice Get the vault parameters address. + * @return The vault parameters address. + */ + function vaultParameters() external view returns (address); +} \ No newline at end of file diff --git a/contracts/interfaces/IWETH.sol b/contracts/interfaces/IWETH.sol index a36c683..93e1a0d 100644 --- a/contracts/interfaces/IWETH.sol +++ b/contracts/interfaces/IWETH.sol @@ -5,9 +5,37 @@ */ pragma solidity ^0.7.6; +/** + * @title Interface for WETH + * @dev Wrapped Ether Interface to interact with WETH tokens in contracts + */ interface IWETH { + /** + * @dev Deposit ether to get wrapped ether + * @notice Call this function along with some ether to get wrapped ether + */ function deposit() external payable; - function transfer(address to, uint value) external returns (bool); - function transferFrom(address from, address to, uint value) external returns (bool); - function withdraw(uint) external; + + /** + * @dev Transfer wrapped ether to a specified address + * @param to The address to transfer to + * @param value The amount of wrapped ether to be transferred + * @return success A boolean that indicates if the operation was successful + */ + function transfer(address to, uint value) external returns (bool success); + + /** + * @dev Transfer wrapped ether from one address to another + * @param from The address which you want to send tokens from + * @param to The address which you want to transfer to + * @param value The amount of wrapped ether to be transferred + * @return success A boolean that indicates if the operation was successful + */ + function transferFrom(address from, address to, uint value) external returns (bool success); + + /** + * @dev Withdraw ether from the contract by unwrapping the wrapped ether + * @param amount The amount of wrapped ether to unwrap + */ + function withdraw(uint amount) external; } \ No newline at end of file diff --git a/contracts/interfaces/IWrappedToUnderlyingOracle.sol b/contracts/interfaces/IWrappedToUnderlyingOracle.sol index bb51409..60ae386 100644 --- a/contracts/interfaces/IWrappedToUnderlyingOracle.sol +++ b/contracts/interfaces/IWrappedToUnderlyingOracle.sol @@ -5,6 +5,16 @@ */ pragma solidity ^0.7.6; +/** + * @title Interface for WrappedToUnderlyingOracle + * @dev Interface for the service that provides mappings from wrapped tokens to their underlying assets. + */ interface IWrappedToUnderlyingOracle { - function assetToUnderlying(address) external view returns (address); -} + + /** + * @notice Retrieves the underlying asset address for a given wrapped token address. + * @param wrappedToken The address of the wrapped token contract. + * @return The address of the underlying asset. + */ + function assetToUnderlying(address wrappedToken) external view returns (address); +} \ No newline at end of file diff --git a/contracts/interfaces/IWstEthToken.sol b/contracts/interfaces/IWstEthToken.sol index 2d9f89f..b9c05da 100644 --- a/contracts/interfaces/IWstEthToken.sol +++ b/contracts/interfaces/IWstEthToken.sol @@ -5,7 +5,22 @@ */ pragma solidity ^0.7.6; +/** + * @title IWstEthToken + * @dev Interface for the Wrapped stETH (wstETH) token contract. + */ interface IWstEthToken { + + /** + * @dev Returns the address of the underlying stETH token. + * @return address The address of the stETH token. + */ function stETH() external view returns (address); + + /** + * @dev Given an amount of wstETH, returns the equivalent amount of stETH. + * @param _wstETHAmount The amount of wstETH to convert. + * @return uint256 The equivalent amount of stETH. + */ function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256); -} +} \ No newline at end of file diff --git a/contracts/interfaces/IcyToken.sol b/contracts/interfaces/IcyToken.sol index 323d104..efa4666 100644 --- a/contracts/interfaces/IcyToken.sol +++ b/contracts/interfaces/IcyToken.sol @@ -5,9 +5,32 @@ */ pragma solidity ^0.7.6; +/** + * @title IcyToken interface + * @dev Interface for cyToken contracts which are interest-bearing tokens representing deposits in the protocol. + */ interface IcyToken { + /** + * @dev Returns the underlying asset address of the cyToken. + * @return The address of the underlying asset. + */ function underlying() external view returns (address); + + /** + * @dev Returns the address of the current implementation. + * @return The address of the implementation contract. + */ function implementation() external view returns (address); + + /** + * @dev Returns the number of decimal places of the cyToken. + * @return The number of decimal places. + */ function decimals() external view returns (uint8); + + /** + * @dev Returns the current exchange rate of the cyToken, scaled by 1e18. + * @return The current exchange rate, scaled by 1e18. + */ function exchangeRateStored() external view returns (uint); -} +} \ No newline at end of file diff --git a/contracts/interfaces/IyvToken.sol b/contracts/interfaces/IyvToken.sol index fe4d492..42ad0f5 100644 --- a/contracts/interfaces/IyvToken.sol +++ b/contracts/interfaces/IyvToken.sol @@ -5,9 +5,32 @@ */ pragma solidity ^0.7.6; +/** + * @title Interface for Yearn Vault Token (yvToken) + */ interface IyvToken { + + /** + * @notice Retrieves the underlying token address. + * @return address The address of the underlying token. + */ function token() external view returns (address); + + /** + * @notice Retrieves the number of decimals for the vault token. + * @return uint256 The number of decimals used by the vault token. + */ function decimals() external view returns (uint256); + + /** + * @notice Retrieves the current price per share of the vault token. + * @return uint256 The current price per share. + */ function pricePerShare() external view returns (uint256); + + /** + * @notice Checks if the vault is in emergency shutdown mode. + * @return bool True if the vault is in emergency shutdown, false otherwise. + */ function emergencyShutdown() external view returns (bool); -} +} \ No newline at end of file diff --git a/contracts/interfaces/curve/ICurvePoolBase.sol b/contracts/interfaces/curve/ICurvePoolBase.sol index 18cc324..2639c99 100644 --- a/contracts/interfaces/curve/ICurvePoolBase.sol +++ b/contracts/interfaces/curve/ICurvePoolBase.sol @@ -7,17 +7,29 @@ pragma solidity ^0.7.6; import "../ICurvePool.sol"; +/** + * @title ICurvePoolBase + * @dev Extension of ICurvePool interface that includes exchange functionality + */ interface ICurvePoolBase is ICurvePool { + /** * @notice Perform an exchange between two coins - * @dev Index values can be found via the `coins` public getter method - * @param i Index value for the coin to send - * @param j Index valie of the coin to recieve - * @param _dx Amount of `i` being exchanged - * @param _min_dy Minimum amount of `j` to receive - * @return Actual amount of `j` received + * @dev Index values can be found via the `coins` public getter method. + * @param i The index value for the coin to send + * @param j The index value for the coin to receive + * @param _dx The amount of `i` being exchanged + * @param _min_dy The minimum amount of `j` to receive + * @return The actual amount of `j` received */ function exchange(int128 i, int128 j, uint256 _dx, uint256 _min_dy) external returns (uint256); + /** + * @notice Calculate the amount of `j` received when exchanging `i` + * @param i The index value for the coin to send + * @param j The index value for the coin to receive + * @param _dx The amount of `i` being exchanged + * @return The calculated amount of `j` that will be received + */ function get_dy(int128 i, int128 j, uint256 _dx) external view returns (uint256); } \ No newline at end of file diff --git a/contracts/interfaces/curve/ICurvePoolCrypto.sol b/contracts/interfaces/curve/ICurvePoolCrypto.sol index 385935f..444d3b6 100644 --- a/contracts/interfaces/curve/ICurvePoolCrypto.sol +++ b/contracts/interfaces/curve/ICurvePoolCrypto.sol @@ -7,7 +7,27 @@ pragma solidity ^0.7.6; import "../ICurvePool.sol"; +/** + * @title ICurvePoolCrypto + * @dev Interface for interacting with the Curve Crypto Pool contract. + */ interface ICurvePoolCrypto is ICurvePool { + + /** + * @notice Exchange one coin for another. + * @param i The index value for the coin to send. + * @param j The index value for the coin to receive. + * @param dx The amount of i being exchanged. + * @param min_dy The minimum amount of j to receive. + */ function exchange(uint256 i, uint256 j, uint256 dx, uint256 min_dy) external; + + /** + * @notice Calculate the amount of coin j one would receive for amount dx of coin i. + * @param i The index value for the coin to send. + * @param j The index value for the coin to receive. + * @param dx The amount of i to be exchanged. + * @return The amount of coin j that would be received. + */ function get_dy(uint256 i, uint256 j, uint256 dx) external view returns (uint256); } \ No newline at end of file diff --git a/contracts/interfaces/curve/ICurvePoolMeta.sol b/contracts/interfaces/curve/ICurvePoolMeta.sol index 9645b09..ce9d80a 100644 --- a/contracts/interfaces/curve/ICurvePoolMeta.sol +++ b/contracts/interfaces/curve/ICurvePoolMeta.sol @@ -7,19 +7,38 @@ pragma solidity ^0.7.6; import "./ICurvePoolBase.sol"; +/** + * @title ICurvePoolMeta + * @dev Interface for interacting with Curve's meta pools, which allow for interactions + * with liquidity pools containing tokens and meta tokens (like 3CRV). + */ interface ICurvePoolMeta is ICurvePoolBase { + /** + * @notice Get the address of the base pool contract + * @dev Returns the contract address of the base pool associated with this meta pool + * @return The address of the base pool contract + */ function base_pool() external view returns (address); /** - * @dev variant of token/3crv pool - * @param i Index value for the underlying coin to send - * @param j Index value of the underlying coin to recieve - * @param _dx Amount of `i` being exchanged - * @param _min_dy Minimum amount of `j` to receive - * @return Actual amount of `j` received + * @notice Exchange an amount of one underlying coin for another in the pool + * @dev This function allows for an exchange between two underlying coins in the pool + * @param i The index value for the underlying coin to send + * @param j The index value of the underlying coin to receive + * @param _dx The amount of coin `i` being exchanged + * @param _min_dy The minimum amount of coin `j` to receive + * @return The actual amount of coin `j` received after the exchange */ function exchange_underlying(int128 i, int128 j, uint256 _dx, uint256 _min_dy) external returns (uint256); + /** + * @notice Calculate the amount of one underlying coin that can be received for another + * @dev Provides a quote of how much of coin `j` one would receive for a given amount of coin `i` + * @param i The index value for the underlying coin to send + * @param j The index value of the underlying coin to receive + * @param _dx The amount of coin `i` being exchanged + * @return The amount of coin `j` that can be received for the given amount of coin `i` + */ function get_dy_underlying(int128 i, int128 j, uint256 _dx) external view returns (uint256); } \ No newline at end of file diff --git a/contracts/interfaces/swappers/ISwapper.sol b/contracts/interfaces/swappers/ISwapper.sol index a1dac26..c908a4b 100644 --- a/contracts/interfaces/swappers/ISwapper.sol +++ b/contracts/interfaces/swappers/ISwapper.sol @@ -5,42 +5,75 @@ */ pragma solidity 0.7.6; - +/** + * @title ISwapper + * @dev Interface for swapping assets with USDP (USD Pegged) token. + */ interface ISwapper { /** - * @notice Predict asset amount after usdp swap + * @notice Predicts the amount of asset that will be received after swapping a given amount of USDP. + * @param _asset The address of the asset to swap to. + * @param _usdpAmountIn The amount of USDP to be swapped. + * @return predictedAssetAmount The predicted amount of asset that will be received. */ function predictAssetOut(address _asset, uint256 _usdpAmountIn) external view returns (uint predictedAssetAmount); /** - * @notice Predict USDP amount after asset swap + * @notice Predicts the amount of USDP that will be received after swapping a given amount of asset. + * @param _asset The address of the asset to swap from. + * @param _assetAmountIn The amount of the asset to be swapped. + * @return predictedUsdpAmount The predicted amount of USDP that will be received. */ function predictUsdpOut(address _asset, uint256 _assetAmountIn) external view returns (uint predictedUsdpAmount); /** - * @notice usdp must be approved to swapper - * @dev asset must be sent to user after swap + * @notice Swaps USDP to a specified asset for a user. + * @dev The user must approve the USDP amount to the swapper contract before calling this function. + * The asset is sent to the user after the swap. + * @param _user The address of the user to receive the swapped asset. + * @param _asset The address of the asset to swap to. + * @param _usdpAmount The amount of USDP to swap. + * @param _minAssetAmount The minimum amount of asset expected to receive. + * @return swappedAssetAmount The actual amount of asset received from the swap. */ function swapUsdpToAsset(address _user, address _asset, uint256 _usdpAmount, uint256 _minAssetAmount) external returns (uint swappedAssetAmount); /** - * @notice asset must be approved to swapper - * @dev usdp must be sent to user after swap + * @notice Swaps an asset to USDP for a user. + * @dev The user must approve the asset amount to the swapper contract before calling this function. + * The USDP is sent to the user after the swap. + * @param _user The address of the user to receive the swapped USDP. + * @param _asset The address of the asset to swap from. + * @param _assetAmount The amount of the asset to swap. + * @param _minUsdpAmount The minimum amount of USDP expected to receive. + * @return swappedUsdpAmount The actual amount of USDP received from the swap. */ function swapAssetToUsdp(address _user, address _asset, uint256 _assetAmount, uint256 _minUsdpAmount) external returns (uint swappedUsdpAmount); /** - * @notice DO NOT SEND tokens to contract manually. For usage in contracts only. - * @dev for gas saving with usage in contracts tokens must be send directly to contract instead - * @dev asset must be sent to user after swap + * @notice Swaps USDP to a specified asset for a user with direct sending of tokens to save gas. + * @dev This function is intended for use in contracts only, to save gas by sending tokens directly to the contract. + * The asset is sent to the user after the swap. + * DO NOT SEND tokens to the contract manually when using this function. + * @param _user The address of the user to receive the swapped asset. + * @param _asset The address of the asset to swap to. + * @param _usdpAmount The amount of USDP to swap. + * @param _minAssetAmount The minimum amount of asset expected to receive. + * @return swappedAssetAmount The actual amount of asset received from the swap. */ function swapUsdpToAssetWithDirectSending(address _user, address _asset, uint256 _usdpAmount, uint256 _minAssetAmount) external returns (uint swappedAssetAmount); /** - * @notice DO NOT SEND tokens to contract manually. For usage in contracts only. - * @dev for gas saving with usage in contracts tokens must be send directly to contract instead - * @dev usdp must be sent to user after swap + * @notice Swaps an asset to USDP for a user with direct sending of tokens to save gas. + * @dev This function is intended for use in contracts only, to save gas by sending tokens directly to the contract. + * The USDP is sent to the user after the swap. + * DO NOT SEND tokens to the contract manually when using this function. + * @param _user The address of the user to receive the swapped USDP. + * @param _asset The address of the asset to swap from. + * @param _assetAmount The amount of the asset to swap. + * @param _minUsdpAmount The minimum amount of USDP expected to receive. + * @return swappedUsdpAmount The actual amount of USDP received from the swap. */ function swapAssetToUsdpWithDirectSending(address _user, address _asset, uint256 _assetAmount, uint256 _minUsdpAmount) external returns (uint swappedUsdpAmount); -} +} \ No newline at end of file diff --git a/contracts/interfaces/swappers/ISwappersRegistry.sol b/contracts/interfaces/swappers/ISwappersRegistry.sol index de7061d..f2337b4 100644 --- a/contracts/interfaces/swappers/ISwappersRegistry.sol +++ b/contracts/interfaces/swappers/ISwappersRegistry.sol @@ -7,15 +7,53 @@ pragma solidity 0.7.6; import "./ISwapper.sol"; - +/** + * @title ISwappersRegistry + * @dev Interface for the registry of Swapper contracts. + */ interface ISwappersRegistry { + /** + * @dev Emitted when a new swapper is added to the registry. + * @param swapper The address of the swapper contract that was added. + */ event SwapperAdded(ISwapper swapper); + + /** + * @dev Emitted when a swapper is removed from the registry. + * @param swapper The address of the swapper contract that was removed. + */ event SwapperRemoved(ISwapper swapper); + /** + * @dev Returns the identifier of a swapper contract. + * @param _swapper The address of the swapper contract. + * @return The identifier of the swapper. + */ function getSwapperId(ISwapper _swapper) external view returns (uint); + + /** + * @dev Returns the swapper contract at a given identifier. + * @param _id The identifier of the swapper. + * @return The swapper contract address. + */ function getSwapper(uint _id) external view returns (ISwapper); + + /** + * @dev Checks if a swapper contract is in the registry. + * @param _swapper The address of the swapper contract. + * @return True if the swapper is in the registry, false otherwise. + */ function hasSwapper(ISwapper _swapper) external view returns (bool); + /** + * @dev Returns the number of swapper contracts in the registry. + * @return The number of swapper contracts. + */ function getSwappersLength() external view returns (uint); + + /** + * @dev Returns an array of all swapper contracts in the registry. + * @return An array of swapper contract addresses. + */ function getSwappers() external view returns (ISwapper[] memory); -} +} \ No newline at end of file diff --git a/contracts/interfaces/vault-managers/parameters/IAssetsBooleanParameters.sol b/contracts/interfaces/vault-managers/parameters/IAssetsBooleanParameters.sol index 22373f2..cb25158 100644 --- a/contracts/interfaces/vault-managers/parameters/IAssetsBooleanParameters.sol +++ b/contracts/interfaces/vault-managers/parameters/IAssetsBooleanParameters.sol @@ -5,12 +5,48 @@ */ pragma solidity ^0.7.6; +/** + * @title IAssetsBooleanParameters + * @dev Interface for setting and getting boolean parameters of assets. + */ interface IAssetsBooleanParameters { + /** + * @dev Emitted when a boolean parameter value is set for an asset. + * @param asset The address of the asset. + * @param param The parameter index being set. + * @param valuesForAsset The new parameter value for the asset. + */ event ValueSet(address indexed asset, uint8 param, uint256 valuesForAsset); + + /** + * @dev Emitted when a boolean parameter value is unset for an asset. + * @param asset The address of the asset. + * @param param The parameter index being unset. + * @param valuesForAsset The previous parameter value for the asset. + */ event ValueUnset(address indexed asset, uint8 param, uint256 valuesForAsset); + /** + * @notice Retrieves the boolean parameter value for a given asset and parameter index. + * @param _asset The address of the asset. + * @param _param The index of the parameter. + * @return The boolean value of the parameter. + */ function get(address _asset, uint8 _param) external view returns (bool); + + /** + * @notice Retrieves all boolean parameter values for a given asset. + * @param _asset The address of the asset. + * @return The uint256 representation of all boolean parameters for the asset. + */ function getAll(address _asset) external view returns (uint256); + + /** + * @notice Sets the boolean parameter value for a given asset. + * @param _asset The address of the asset. + * @param _param The index of the parameter to set. + * @param _value The boolean value to set for the parameter. + */ function set(address _asset, uint8 _param, bool _value) external; -} +} \ No newline at end of file diff --git a/contracts/interfaces/vault-managers/parameters/IVaultManagerBorrowFeeParameters.sol b/contracts/interfaces/vault-managers/parameters/IVaultManagerBorrowFeeParameters.sol index 590f413..4c571c1 100644 --- a/contracts/interfaces/vault-managers/parameters/IVaultManagerBorrowFeeParameters.sol +++ b/contracts/interfaces/vault-managers/parameters/IVaultManagerBorrowFeeParameters.sol @@ -5,49 +5,59 @@ */ pragma solidity ^0.7.6; +/** + * @title IVaultManagerBorrowFeeParameters + * @dev Interface for managing borrow fee parameters in a vault. + */ interface IVaultManagerBorrowFeeParameters { /** - * @notice 1 = 100% = 10000 basis points - **/ + * @dev Returns the constant representing the number of basis points in one. + * @return The number of basis points in one. + */ function BASIS_POINTS_IN_1() external view returns (uint); /** - * @notice Borrow fee receiver - **/ + * @dev Returns the address where borrow fees are sent. + * @return The address of the fee receiver. + */ function feeReceiver() external view returns (address); /** - * @notice Sets the borrow fee receiver. Only manager is able to call this function - * @param newFeeReceiver The address of fee receiver - **/ + * @dev Sets the address that receives the borrow fee. + * @param newFeeReceiver The address of the new fee receiver. + * @notice Only the manager can call this function. + */ function setFeeReceiver(address newFeeReceiver) external; /** - * @notice Sets the base borrow fee in basis points (1bp = 0.01% = 0.0001). Only manager is able to call this function - * @param newBaseBorrowFeeBasisPoints The borrow fee in basis points - **/ + * @dev Sets the base borrow fee in basis points. + * @param newBaseBorrowFeeBasisPoints The new borrow fee in basis points. + * @notice Only the manager can call this function. + */ function setBaseBorrowFee(uint16 newBaseBorrowFeeBasisPoints) external; /** - * @notice Sets the borrow fee for a particular collateral in basis points (1bp = 0.01% = 0.0001). Only manager is able to call this function - * @param asset The address of the main collateral token - * @param newEnabled Is custom fee enabled for asset - * @param newFeeBasisPoints The borrow fee in basis points - **/ + * @dev Sets the borrow fee for a specific collateral in basis points. + * @param asset The address of the collateral token. + * @param newEnabled Determines if the custom fee is enabled for the asset. + * @param newFeeBasisPoints The new borrow fee in basis points. + * @notice Only the manager can call this function. + */ function setAssetBorrowFee(address asset, bool newEnabled, uint16 newFeeBasisPoints) external; /** - * @notice Returns borrow fee for particular collateral in basis points (1bp = 0.01% = 0.0001) - * @param asset The address of the main collateral token - * @return feeBasisPoints The borrow fee in basis points - **/ + * @dev Retrieves the borrow fee for a specific collateral in basis points. + * @param asset The address of the collateral token. + * @return feeBasisPoints The borrow fee in basis points. + */ function getBorrowFee(address asset) external view returns (uint16 feeBasisPoints); /** - * @notice Returns borrow fee for usdp amount for particular collateral - * @param asset The address of the main collateral token - * @return The borrow fee - **/ + * @dev Calculates the borrow fee amount in USDP for a given amount and collateral. + * @param asset The address of the collateral token. + * @param usdpAmount The amount of USDP for which to calculate the fee. + * @return The calculated borrow fee. + */ function calcBorrowFeeAmount(address asset, uint usdpAmount) external view returns (uint); -} +} \ No newline at end of file diff --git a/contracts/interfaces/vault-managers/parameters/IVaultManagerParameters.sol b/contracts/interfaces/vault-managers/parameters/IVaultManagerParameters.sol index c1f608e..20d4ac0 100644 --- a/contracts/interfaces/vault-managers/parameters/IVaultManagerParameters.sol +++ b/contracts/interfaces/vault-managers/parameters/IVaultManagerParameters.sol @@ -5,15 +5,76 @@ */ pragma solidity ^0.7.6; +/** + * @title IVaultManagerParameters + * @dev Interface for interacting with Vault Manager Parameters in Unit Protocol. + */ interface IVaultManagerParameters { - function devaluationPeriod ( address ) external view returns ( uint256 ); - function initialCollateralRatio ( address ) external view returns ( uint256 ); - function liquidationDiscount ( address ) external view returns ( uint256 ); - function liquidationRatio ( address ) external view returns ( uint256 ); - function maxColPercent ( address ) external view returns ( uint256 ); - function minColPercent ( address ) external view returns ( uint256 ); - function setColPartRange ( address asset, uint256 min, uint256 max ) external; - function setCollateral ( + /** + * @notice Gets the devaluation period of a collateral asset. + * @param asset The address of the collateral asset. + * @return The devaluation period in seconds. + */ + function devaluationPeriod(address asset) external view returns (uint256); + + /** + * @notice Gets the initial collateral ratio for a collateral asset. + * @param asset The address of the collateral asset. + * @return The initial collateral ratio in percentage. + */ + function initialCollateralRatio(address asset) external view returns (uint256); + + /** + * @notice Gets the liquidation discount for a collateral asset. + * @param asset The address of the collateral asset. + * @return The liquidation discount in percentage. + */ + function liquidationDiscount(address asset) external view returns (uint256); + + /** + * @notice Gets the liquidation ratio for a collateral asset. + * @param asset The address of the collateral asset. + * @return The liquidation ratio in percentage. + */ + function liquidationRatio(address asset) external view returns (uint256); + + /** + * @notice Gets the maximum collateral percentage for a collateral asset. + * @param asset The address of the collateral asset. + * @return The maximum collateral percentage in percentage. + */ + function maxColPercent(address asset) external view returns (uint256); + + /** + * @notice Gets the minimum collateral percentage for a collateral asset. + * @param asset The address of the collateral asset. + * @return The minimum collateral percentage in percentage. + */ + function minColPercent(address asset) external view returns (uint256); + + /** + * @notice Sets the collateral percentage range for a given asset. + * @param asset The address of the collateral asset. + * @param min The minimum collateral percentage. + * @param max The maximum collateral percentage. + */ + function setColPartRange(address asset, uint256 min, uint256 max) external; + + /** + * @notice Sets various parameters for a collateral asset. + * @param asset The address of the collateral asset. + * @param stabilityFeeValue The stability fee value. + * @param liquidationFeeValue The liquidation fee value. + * @param initialCollateralRatioValue The initial collateral ratio value. + * @param liquidationRatioValue The liquidation ratio value. + * @param liquidationDiscountValue The liquidation discount value. + * @param devaluationPeriodValue The devaluation period value in seconds. + * @param usdpLimit The USDP limit for this collateral. + * @param oracles The array of oracle addresses. + * @param minColP The minimum collateral percentage. + * @param maxColP The maximum collateral percentage. + */ + function setCollateral( address asset, uint256 stabilityFeeValue, uint256 liquidationFeeValue, @@ -26,9 +87,38 @@ interface IVaultManagerParameters { uint256 minColP, uint256 maxColP ) external; - function setDevaluationPeriod ( address asset, uint256 newValue ) external; - function setInitialCollateralRatio ( address asset, uint256 newValue ) external; - function setLiquidationDiscount ( address asset, uint256 newValue ) external; - function setLiquidationRatio ( address asset, uint256 newValue ) external; - function vaultParameters ( ) external view returns ( address ); -} + + /** + * @notice Sets the devaluation period for a collateral asset. + * @param asset The address of the collateral asset. + * @param newValue The new devaluation period in seconds. + */ + function setDevaluationPeriod(address asset, uint256 newValue) external; + + /** + * @notice Sets the initial collateral ratio for a collateral asset. + * @param asset The address of the collateral asset. + * @param newValue The new initial collateral ratio in percentage. + */ + function setInitialCollateralRatio(address asset, uint256 newValue) external; + + /** + * @notice Sets the liquidation discount for a collateral asset. + * @param asset The address of the collateral asset. + * @param newValue The new liquidation discount in percentage. + */ + function setLiquidationDiscount(address asset, uint256 newValue) external; + + /** + * @notice Sets the liquidation ratio for a collateral asset. + * @param asset The address of the collateral asset. + * @param newValue The new liquidation ratio in percentage. + */ + function setLiquidationRatio(address asset, uint256 newValue) external; + + /** + * @notice Gets the address of the vault parameters contract. + * @return The address of the vault parameters contract. + */ + function vaultParameters() external view returns (address); +} \ No newline at end of file diff --git a/contracts/interfaces/wrapped-assets/IBoneLocker.sol b/contracts/interfaces/wrapped-assets/IBoneLocker.sol index 05c7f2b..7d61e9c 100644 --- a/contracts/interfaces/wrapped-assets/IBoneLocker.sol +++ b/contracts/interfaces/wrapped-assets/IBoneLocker.sol @@ -6,27 +6,73 @@ pragma solidity 0.7.6; /** - * @dev BoneToken locker contract interface + * @title Interface for BoneToken Locker Contract + * @dev This interface defines the functions for locking BoneTokens and claiming them after a locking period. */ interface IBoneLocker { - function lockInfoByUser(address, uint256) external view returns (uint256, uint256, bool); + /** + * @dev Retrieves lock information for a user by index. + * @param user The address of the user whose lock info is being queried. + * @param index The index of the user's lock info to retrieve. + * @return amount The amount of tokens locked. + * @return timestamp The timestamp when the tokens were locked. + * @return isDev Indicates if the locked tokens belong to a developer. + */ + function lockInfoByUser(address user, uint256 index) external view returns (uint256 amount, uint256 timestamp, bool isDev); + /** + * @dev Retrieves the current locking period. + * @return The duration of the locking period in seconds. + */ function lockingPeriod() external view returns (uint256); - // function to claim all the tokens locked for a user, after the locking period + /** + * @dev Claims all tokens locked for a user after the locking period has ended. + * @param r The round or batch number for claiming. + * @param user The address of the user whose tokens are being claimed. + */ function claimAllForUser(uint256 r, address user) external; - // function to claim all the tokens locked by user, after the locking period + /** + * @dev Claims all tokens locked by the caller after the locking period has ended. + * @param r The round or batch number for claiming. + */ function claimAll(uint256 r) external; - // function to get claimable amount for any user + /** + * @dev Retrieves the claimable amount of tokens for a user. + * @param _user The address of the user whose claimable amount is being queried. + * @return The amount of tokens that the user can currently claim. + */ function getClaimableAmount(address _user) external view returns(uint256); - // get the left and right headers for a user, left header is the index counter till which we have already iterated, right header is basically the length of user's lockInfo array - function getLeftRightCounters(address _user) external view returns(uint256, uint256); + /** + * @dev Retrieves the left and right counters for a user's lock info. + * @param _user The address of the user whose counters are being queried. + * @return leftCounter The index counter up to which the user's lock info has been iterated. + * @return rightCounter The length of the user's lockInfo array, indicating the total number of locks. + */ + function getLeftRightCounters(address _user) external view returns(uint256 leftCounter, uint256 rightCounter); + /** + * @dev Locks a specified amount of tokens for a user. + * @param _holder The address of the user for whom the tokens are being locked. + * @param _amount The amount of tokens to lock. + * @param _isDev Indicates if the locked tokens belong to a developer. + */ function lock(address _holder, uint256 _amount, bool _isDev) external; + + /** + * @dev Sets a new locking period. + * @param _newLockingPeriod The new locking period duration in seconds. + * @param _newDevLockingPeriod The new locking period duration for developers in seconds. + */ function setLockingPeriod(uint256 _newLockingPeriod, uint256 _newDevLockingPeriod) external; + + /** + * @dev Allows the owner to withdraw all tokens from the contract in case of an emergency. + * @param _to The address where the withdrawn tokens will be transferred. + */ function emergencyWithdrawOwner(address _to) external; } \ No newline at end of file diff --git a/contracts/interfaces/wrapped-assets/IBoneToken.sol b/contracts/interfaces/wrapped-assets/IBoneToken.sol index 60cc613..47d45a1 100644 --- a/contracts/interfaces/wrapped-assets/IBoneToken.sol +++ b/contracts/interfaces/wrapped-assets/IBoneToken.sol @@ -7,6 +7,17 @@ pragma solidity 0.7.6; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +/** + * @title IBoneToken Interface + * @dev Interface for the BoneToken which extends the IERC20 standard with a minting function. + */ interface IBoneToken is IERC20 { + + /** + * @notice Mints tokens to the specified address. + * @dev Allows for the creation of tokens to be added to the supply. + * @param _to The address that will receive the minted tokens. + * @param _amount The amount of tokens to mint. + */ function mint(address _to, uint256 _amount) external; } \ No newline at end of file diff --git a/contracts/interfaces/wrapped-assets/ISushiSwapLpToken.sol b/contracts/interfaces/wrapped-assets/ISushiSwapLpToken.sol index 6bb9fe7..d9b9194 100644 --- a/contracts/interfaces/wrapped-assets/ISushiSwapLpToken.sol +++ b/contracts/interfaces/wrapped-assets/ISushiSwapLpToken.sol @@ -7,7 +7,21 @@ pragma solidity 0.7.6; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +/** + * @title ISushiSwapLpToken + * @dev Interface for SushiSwap's LP Token, extending IERC20 with token0 and token1 functions. + */ interface ISushiSwapLpToken is IERC20 /* IERC20WithOptional */ { + + /** + * @notice Get the address of the first token forming the liquidity pair. + * @return address The address of the first token. + */ function token0() external view returns (address); + + /** + * @notice Get the address of the second token forming the liquidity pair. + * @return address The address of the second token. + */ function token1() external view returns (address); } \ No newline at end of file diff --git a/contracts/interfaces/wrapped-assets/ITopDog.sol b/contracts/interfaces/wrapped-assets/ITopDog.sol index a09d8e1..6967f7c 100644 --- a/contracts/interfaces/wrapped-assets/ITopDog.sol +++ b/contracts/interfaces/wrapped-assets/ITopDog.sol @@ -11,20 +11,83 @@ import "./IBoneLocker.sol"; import "./IBoneToken.sol"; /** + * @title ITopDog + * @dev Interface for interacting with the TopDog contract. * See https://etherscan.io/address/0x94235659cf8b805b2c658f9ea2d6d6ddbb17c8d7#code */ interface ITopDog { + /** + * @dev Returns the address of the BONE token contract. + * @return IBoneToken Address of the BONE token contract. + */ function bone() external view returns (IBoneToken); + + /** + * @dev Returns the address of the BoneLocker contract. + * @return IBoneLocker Address of the BoneLocker contract. + */ function boneLocker() external view returns (IBoneLocker); - function poolInfo(uint256) external view returns (IERC20, uint256, uint256, uint256); + + /** + * @dev Provides information about a specific liquidity pool. + * @param _pid The index of the pool. + * @return IERC20 The address of the pool's token contract. + * @return uint256 The allocation point assigned to the pool. + * @return uint256 The last block number that BONE distribution occurs. + * @return uint256 The accumulated BONE per share. + */ + function poolInfo(uint256 _pid) external view returns (IERC20, uint256, uint256, uint256); + + /** + * @dev Returns the total number of liquidity pools. + * @return uint256 The total number of liquidity pools. + */ function poolLength() external view returns (uint256); - function userInfo(uint256, address) external view returns (uint256, uint256); + /** + * @dev Provides information about a user's position in a specific pool. + * @param _pid The index of the pool. + * @param _user The address of the user. + * @return uint256 The amount of pool tokens the user has provided. + * @return uint256 The reward debt of the user. + */ + function userInfo(uint256 _pid, address _user) external view returns (uint256, uint256); + + /** + * @dev Returns the percentage of BONE tokens minted as rewards. + * @return uint256 The reward mint percent. + */ function rewardMintPercent() external view returns (uint256); + + /** + * @dev Calculates the pending BONE rewards for a user in a given pool. + * @param _pid The index of the pool. + * @param _user The address of the user. + * @return uint256 The amount of pending BONE rewards. + */ function pendingBone(uint256 _pid, address _user) external view returns (uint256); + + /** + * @notice Deposit pool tokens to TopDog for BONE allocation. + * @dev Deposits tokens into a specific pool for BONE allocation. + * @param _pid The index of the pool. + * @param _amount The amount of pool tokens to deposit. + */ function deposit(uint256 _pid, uint256 _amount) external; + + /** + * @notice Withdraw pool tokens from TopDog. + * @dev Withdraws pool tokens from a specific pool. + * @param _pid The index of the pool. + * @param _amount The amount of pool tokens to withdraw. + */ function withdraw(uint256 _pid, uint256 _amount) external; + /** + * @notice Perform an emergency withdrawal of pool tokens from TopDog. + * @dev Withdraws all pool tokens from a specific pool without caring about rewards. + * @param _pid The index of the pool. + */ function emergencyWithdraw(uint256 _pid) external; } \ No newline at end of file diff --git a/contracts/interfaces/wrapped-assets/IWrappedAsset.sol b/contracts/interfaces/wrapped-assets/IWrappedAsset.sol index 1e7b58f..1d560b2 100644 --- a/contracts/interfaces/wrapped-assets/IWrappedAsset.sol +++ b/contracts/interfaces/wrapped-assets/IWrappedAsset.sol @@ -9,6 +9,7 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWrappedAsset is IERC20 /* IERC20WithOptional */ { + /* Events */ event Deposit(address indexed user, uint256 amount); event Withdraw(address indexed user, uint256 amount); event PositionMoved(address indexed userFrom, address indexed userTo, uint256 amount); @@ -22,41 +23,49 @@ interface IWrappedAsset is IERC20 /* IERC20WithOptional */ { event AllowedBoneLockerSelectorRemoved(address boneLocker, bytes4 selector); /** - * @notice Get underlying token + * @notice Returns the underlying token of the wrapped asset + * @return The underlying IERC20 token */ function getUnderlyingToken() external view returns (IERC20); /** - * @notice deposit underlying token and send wrapped token to user - * @dev Important! Only user or trusted contracts must be able to call this method + * @notice Deposits the underlying token and mints the wrapped token to the specified user + * @param _userAddr The address of the user to receive the wrapped tokens + * @param _amount The amount of the underlying token to deposit */ function deposit(address _userAddr, uint256 _amount) external; /** - * @notice get wrapped token and return underlying - * @dev Important! Only user or trusted contracts must be able to call this method + * @notice Withdraws the underlying token by burning the wrapped token + * @param _userAddr The address of the user to return the underlying tokens to + * @param _amount The amount of the wrapped token to burn */ function withdraw(address _userAddr, uint256 _amount) external; /** - * @notice get pending reward amount for user if reward is supported + * @notice Returns the pending reward amount for the user if rewards are supported + * @param _userAddr The address of the user to check the reward for + * @return The amount of pending reward */ function pendingReward(address _userAddr) external view returns (uint256); /** - * @notice claim pending reward for user if reward is supported + * @notice Claims the pending reward for the user if rewards are supported + * @param _userAddr The address of the user to claim the reward for */ function claimReward(address _userAddr) external; /** - * @notice Manually move position (or its part) to another user (for example in case of liquidation) - * @dev Important! Only trusted contracts must be able to call this method + * @notice Moves a position, or a portion of it, to another user (e.g., in case of liquidation) + * @param _userAddrFrom The address of the user from whom the position is moved + * @param _userAddrTo The address of the user to whom the position is moved + * @param _amount The amount of the position to move */ function movePosition(address _userAddrFrom, address _userAddrTo, uint256 _amount) external; /** - * @dev function for checks that asset is unitprotocol wrapped asset. - * @dev For wrapped assets must return keccak256("UnitProtocolWrappedAsset") + * @notice Checks if an asset is a Unit Protocol wrapped asset + * @return Returns the keccak256 hash of "UnitProtocolWrappedAsset" if the asset is a wrapped asset */ function isUnitProtocolWrappedAsset() external view returns (bytes32); -} +} \ No newline at end of file diff --git a/contracts/oracles/BearingAssetOracle.sol b/contracts/oracles/BearingAssetOracle.sol index ced32a8..f8e598b 100644 --- a/contracts/oracles/BearingAssetOracle.sol +++ b/contracts/oracles/BearingAssetOracle.sol @@ -14,26 +14,49 @@ import "../interfaces/IOracleEth.sol"; /** * @title BearingAssetOracle * @dev Wrapper to quote bearing assets like xSUSHI - **/ + */ contract BearingAssetOracle is IOracleUsd, Auth { IOracleRegistry public immutable oracleRegistry; + // Maps bearing asset to its underlying asset mapping (address => address) underlyings; + /** + * @dev Emitted when a new underlying is set for a bearing asset. + * @param bearing The address of the bearing asset + * @param underlying The address of the underlying asset + */ event NewUnderlying(address indexed bearing, address indexed underlying); + /** + * @dev Constructs the BearingAssetOracle contract. + * @param _vaultParameters The address of the VaultParameters contract + * @param _oracleRegistry The address of the OracleRegistry contract + */ constructor(address _vaultParameters, address _oracleRegistry) Auth(_vaultParameters) { require(_vaultParameters != address(0) && _oracleRegistry != address(0), "Unit Protocol: ZERO_ADDRESS"); oracleRegistry = IOracleRegistry(_oracleRegistry); } + /** + * @dev Sets the underlying asset for a given bearing asset. + * @notice Only the manager can call this function. + * @param bearing The address of the bearing asset + * @param underlying The address of the underlying asset + */ function setUnderlying(address bearing, address underlying) external onlyManager { underlyings[bearing] = underlying; emit NewUnderlying(bearing, underlying); } - // returns Q112-encoded value + /** + * @dev Returns the USD value of the bearing asset provided. + * @notice Returns a Q112-encoded value (to maintain precision). + * @param bearing The address of the bearing asset + * @param amount The amount of the bearing asset + * @return The USD value of the bearing asset amount provided + */ function assetToUsd(address bearing, uint amount) public override view returns (uint) { if (amount == 0) return 0; (address underlying, uint underlyingAmount) = bearingToUnderlying(bearing, amount); @@ -42,6 +65,12 @@ contract BearingAssetOracle is IOracleUsd, Auth { return _oracleForUnderlying.assetToUsd(underlying, underlyingAmount); } + /** + * @dev Converts the amount of bearing asset into the equivalent amount of its underlying asset. + * @param bearing The address of the bearing asset + * @param amount The amount of the bearing asset + * @return The address of the underlying asset and the equivalent amount of the underlying asset + */ function bearingToUnderlying(address bearing, uint amount) public view returns (address, uint) { address _underlying = underlyings[bearing]; require(_underlying != address(0), "Unit Protocol: UNDEFINED_UNDERLYING"); @@ -51,4 +80,4 @@ contract BearingAssetOracle is IOracleUsd, Auth { return (_underlying, amount * _reserve / _totalSupply); } -} +} \ No newline at end of file diff --git a/contracts/oracles/BridgedUsdpOracle.sol b/contracts/oracles/BridgedUsdpOracle.sol index dd8efde..d126c3b 100644 --- a/contracts/oracles/BridgedUsdpOracle.sol +++ b/contracts/oracles/BridgedUsdpOracle.sol @@ -9,30 +9,47 @@ import "../interfaces/IOracleUsd.sol"; import "../helpers/SafeMath.sol"; import "../Auth2.sol"; -/** +/* * @title BridgedUSDPOracle - * @dev Oracle to quote bridged from other chains USDP - **/ + * @dev Oracle to quote bridged from other chains USDP. Implements the IOracleUsd interface. + */ contract BridgedUsdpOracle is IOracleUsd, Auth2 { using SafeMath for uint; + // Q112 is used to store values with 112 decimal places. uint public constant Q112 = 2 ** 112; + // Mapping to keep track of addresses that are recognized as bridged USDP tokens. mapping (address => bool) public bridgedUsdp; + // Event emitted when a new USDP address is added. event Added(address _usdp); + // Event emitted when an existing USDP address is removed. event Removed(address _usdp); + /** + * @dev Constructor that initializes the contract's state. + * @param vaultParameters The address of the contract containing vault parameters. + * @param _bridgedUsdp Array of addresses to be initially recognized as bridged USDP tokens. + */ constructor(address vaultParameters, address[] memory _bridgedUsdp) Auth2(vaultParameters) { for (uint i = 0; i < _bridgedUsdp.length; i++) { _add(_bridgedUsdp[i]); } } + /** + * @dev Adds a new USDP address to the list of recognized bridged USDP tokens. Only the manager can call it. + * @param _usdp The address of the USDP token to add. + */ function add(address _usdp) external onlyManager { _add(_usdp); } + /** + * @dev Internal function to add a new USDP address to the list of recognized bridged USDP tokens. + * @param _usdp The address of the USDP token to add. + */ function _add(address _usdp) private { require(_usdp != address(0), 'Unit Protocol: ZERO_ADDRESS'); require(!bridgedUsdp[_usdp], 'Unit Protocol: ALREADY_ADDED'); @@ -41,6 +58,10 @@ contract BridgedUsdpOracle is IOracleUsd, Auth2 { emit Added(_usdp); } + /** + * @dev Removes a USDP address from the list of recognized bridged USDP tokens. Only the manager can call it. + * @param _usdp The address of the USDP token to remove. + */ function remove(address _usdp) external onlyManager { require(_usdp != address(0), 'Unit Protocol: ZERO_ADDRESS'); require(bridgedUsdp[_usdp], 'Unit Protocol: WAS_NOT_ADDED'); @@ -49,9 +70,14 @@ contract BridgedUsdpOracle is IOracleUsd, Auth2 { emit Removed(_usdp); } - // returns Q112-encoded value + /** + * @dev Converts the asset amount to the equivalent USD value. The returned value is Q112-encoded. + * @param asset The address of the asset to convert. + * @param amount The amount of the asset to convert. + * @return The equivalent USD value of the asset amount, Q112-encoded. + */ function assetToUsd(address asset, uint amount) public override view returns (uint) { require(bridgedUsdp[asset], 'Unit Protocol: TOKEN_IS_NOT_SUPPORTED'); return amount.mul(Q112); } -} +} \ No newline at end of file diff --git a/contracts/oracles/ChainlinkedKeydonixOracleMainAssetAbstract.sol b/contracts/oracles/ChainlinkedKeydonixOracleMainAssetAbstract.sol index 9abdf26..98d093c 100644 --- a/contracts/oracles/ChainlinkedKeydonixOracleMainAssetAbstract.sol +++ b/contracts/oracles/ChainlinkedKeydonixOracleMainAssetAbstract.sol @@ -8,19 +8,32 @@ pragma solidity 0.7.6; import "./KeydonixOracleAbstract.sol"; pragma experimental ABIEncoderV2; - /** * @title ChainlinkedKeydonixOracleMainAssetAbstract - **/ + * @dev Abstract contract for Chainlinked Keydonix Oracle for main assets. + */ abstract contract ChainlinkedKeydonixOracleMainAssetAbstract is KeydonixOracleAbstract { + /// @notice Address of Wrapped Ether (WETH) address public WETH; + /** + * @notice Converts the amount of the asset to ETH using proof data. + * @param asset The address of the asset to be converted. + * @param amount The amount of the asset to be converted. + * @param proofData The proof data required for the conversion. + * @return The equivalent amount of ETH. + */ function assetToEth( address asset, uint amount, ProofDataStruct memory proofData ) public virtual view returns (uint); + /** + * @notice Converts the amount of ETH to USD. + * @param ethAmount The amount of ETH to be converted. + * @return The equivalent amount of USD. + */ function ethToUsd(uint ethAmount) public virtual view returns (uint); -} +} \ No newline at end of file diff --git a/contracts/oracles/ChainlinkedKeydonixOraclePoolTokenAbstract.sol b/contracts/oracles/ChainlinkedKeydonixOraclePoolTokenAbstract.sol index e19961e..c5879f9 100644 --- a/contracts/oracles/ChainlinkedKeydonixOraclePoolTokenAbstract.sol +++ b/contracts/oracles/ChainlinkedKeydonixOraclePoolTokenAbstract.sol @@ -9,11 +9,14 @@ pragma experimental ABIEncoderV2; import "./ChainlinkedKeydonixOracleMainAssetAbstract.sol"; import "./KeydonixOracleAbstract.sol"; - /** - * @title ChainlinkedKeydonixOraclePoolTokenAbstract - **/ + * @title Abstract contract for Chainlinked Keydonix Oracle for Pool Tokens + * @dev This abstract contract provides an interface for Chainlinked Keydonix Oracle for Pool Tokens. + */ abstract contract ChainlinkedKeydonixOraclePoolTokenAbstract is KeydonixOracleAbstract { + /** + * @notice Reference to the ChainlinkedKeydonixOracleMainAssetAbstract contract + */ ChainlinkedKeydonixOracleMainAssetAbstract public uniswapOracleMainAsset; -} +} \ No newline at end of file diff --git a/contracts/oracles/ChainlinkedOracleMainAsset.sol b/contracts/oracles/ChainlinkedOracleMainAsset.sol index 14301ea..f27239d 100644 --- a/contracts/oracles/ChainlinkedOracleMainAsset.sol +++ b/contracts/oracles/ChainlinkedOracleMainAsset.sol @@ -14,23 +14,40 @@ import "../interfaces/IToken.sol"; /** * @title ChainlinkedOracleMainAsset - * @dev Calculates the USD price of desired tokens - **/ + * @dev Calculates the USD price of desired tokens using Chainlink Oracles. + * It supports both direct USD pricing and indirect pricing via ETH. + */ contract ChainlinkedOracleMainAsset is IOracleUsd, IOracleEth, Auth { using SafeMath for uint; + // Mapping from token addresses to their USD Chainlink Aggregator mapping (address => address) public usdAggregators; + + // Mapping from token addresses to their ETH Chainlink Aggregator mapping (address => address) public ethAggregators; + // Constant to convert raw Chainlink responses to 18 decimal places uint public constant Q112 = 2 ** 112; + // Constants to define price feed types uint public constant USD_TYPE = 0; uint public constant ETH_TYPE = 1; + // Address of the WETH token address public immutable WETH; + // Event emitted when a new aggregator is set event NewAggregator(address indexed asset, address indexed aggregator, uint aggType); + /** + * @dev Constructor that initializes the contract with predefined aggregators. + * @param tokenAddresses1 Array of token addresses for USD aggregators. + * @param _usdAggregators Array of USD Chainlink Aggregator addresses. + * @param tokenAddresses2 Array of token addresses for ETH aggregators. + * @param _ethAggregators Array of ETH Chainlink Aggregator addresses. + * @param weth Address of the WETH token. + * @param vaultParameters Address of the system's VaultParameters contract. + */ constructor( address[] memory tokenAddresses1, address[] memory _usdAggregators, @@ -58,6 +75,14 @@ contract ChainlinkedOracleMainAsset is IOracleUsd, IOracleEth, Auth { } } + /** + * @dev Sets new USD and ETH aggregators for specified tokens. + * Can only be called by the manager role. + * @param tokenAddresses1 Array of token addresses for USD aggregators. + * @param _usdAggregators Array of new USD Chainlink Aggregator addresses. + * @param tokenAddresses2 Array of token addresses for ETH aggregators. + * @param _ethAggregators Array of new ETH Chainlink Aggregator addresses. + */ function setAggregators( address[] calldata tokenAddresses1, address[] calldata _usdAggregators, @@ -79,11 +104,11 @@ contract ChainlinkedOracleMainAsset is IOracleUsd, IOracleEth, Auth { } /** - * @notice {asset}/USD or {asset}/ETH pair must be registered at Chainlink - * @param asset The token address - * @param amount Amount of tokens - * @return Q112-encoded price of asset amount in USD - **/ + * @dev Converts the asset amount to its equivalent USD value. + * @param asset The address of the token to convert. + * @param amount The amount of the token to convert. + * @return The Q112-encoded price of the asset amount in USD. + */ function assetToUsd(address asset, uint amount) public override view returns (uint) { if (amount == 0) { return 0; @@ -94,6 +119,12 @@ contract ChainlinkedOracleMainAsset is IOracleUsd, IOracleEth, Auth { return ethToUsd(assetToEth(asset, amount)); } + /** + * @dev Internal function to convert the asset amount to its equivalent USD value using the USD aggregator. + * @param asset The address of the token to convert. + * @param amount The amount of the token to convert. + * @return The Q112-encoded price of the asset amount in USD. + */ function _assetToUsd(address asset, uint amount) internal view returns (uint) { IAggregator agg = IAggregator(usdAggregators[asset]); (, int256 answer, , uint256 updatedAt, ) = agg.latestRoundData(); @@ -108,11 +139,11 @@ contract ChainlinkedOracleMainAsset is IOracleUsd, IOracleEth, Auth { } /** - * @notice {asset}/ETH pair must be registered at Chainlink - * @param asset The token address - * @param amount Amount of tokens - * @return Q112-encoded price of asset amount in ETH - **/ + * @dev Converts the asset amount to its equivalent ETH value. + * @param asset The address of the token to convert. + * @param amount The amount of the token to convert. + * @return The Q112-encoded price of the asset amount in ETH. + */ function assetToEth(address asset, uint amount) public view override returns (uint) { if (amount == 0) { return 0; @@ -140,9 +171,10 @@ contract ChainlinkedOracleMainAsset is IOracleUsd, IOracleEth, Auth { } /** - * @notice ETH/USD price feed from Chainlink, see for more info: https://feeds.chain.link/eth-usd - * returns The price of given amount of Ether in USD (0 decimals) - **/ + * @dev Converts the ETH amount to its equivalent USD value using the Chainlink ETH/USD price feed. + * @param ethAmount The amount of ETH to convert. + * @return The price of the given amount of Ether in USD (0 decimals). + */ function ethToUsd(uint ethAmount) public override view returns (uint) { IAggregator agg = IAggregator(usdAggregators[WETH]); (, int256 answer, , uint256 updatedAt, ) = agg.latestRoundData(); @@ -150,10 +182,15 @@ contract ChainlinkedOracleMainAsset is IOracleUsd, IOracleEth, Auth { return ethAmount.mul(uint(answer)).div(10 ** agg.decimals()); } + /** + * @dev Converts the USD amount to its equivalent ETH value using the Chainlink ETH/USD price feed. + * @param _usdAmount The amount of USD to convert. + * @return The price of the given amount of USD in ETH (0 decimals). + */ function usdToEth(uint _usdAmount) public override view returns (uint) { IAggregator agg = IAggregator(usdAggregators[WETH]); (, int256 answer, , uint256 updatedAt, ) = agg.latestRoundData(); require(updatedAt > block.timestamp - 6 hours, "Unit Protocol: STALE_CHAINLINK_PRICE"); return _usdAmount.mul(10 ** agg.decimals()).div(uint(answer)); } -} +} \ No newline at end of file diff --git a/contracts/oracles/CurveLPOracle.sol b/contracts/oracles/CurveLPOracle.sol index aa84a00..4f50a5d 100644 --- a/contracts/oracles/CurveLPOracle.sol +++ b/contracts/oracles/CurveLPOracle.sol @@ -16,8 +16,8 @@ import "../interfaces/ICurvePool.sol"; /** * @title CurveLPOracle - * @dev Oracle to quote curve LP tokens - **/ + * @dev Oracle to quote curve LP tokens. + */ contract CurveLPOracle is IOracleUsd { using SafeMath for uint; @@ -30,16 +30,28 @@ contract CurveLPOracle is IOracleUsd { IOracleRegistry public immutable oracleRegistry; /** - * @param _curveProvider The address of the Curve Provider. Mainnet: 0x0000000022D53366457F9d5E68Ec105046FC4383 - * @param _oracleRegistry The address of the OracleRegistry contract - **/ + * @dev Constructs the CurveLPOracle contract. + * @param _curveProvider The address of the Curve Provider. + * @param _oracleRegistry The address of the OracleRegistry contract. + */ constructor(address _curveProvider, address _oracleRegistry) { require(_curveProvider != address(0) && _oracleRegistry != address(0), "Unit Protocol: ZERO_ADDRESS"); curveProvider = ICurveProvider(_curveProvider); oracleRegistry = IOracleRegistry(_oracleRegistry); } - // returns Q112-encoded value + /** + * @notice Converts the amount of the asset into the equivalent USD value. + * @dev Returns the Q112-encoded value of the asset in USD. + * @param asset The address of the LP token to be quoted. + * @param amount The amount of the LP token. + * @return The USD value of the input amount, Q112-encoded. + * @throws "Unit Protocol: ZERO_ADDRESS" if the Curve Provider or OracleRegistry is a zero address. + * @throws "Unit Protocol: NOT_A_CURVE_LP" if the provided asset is not a Curve LP token. + * @throws "Unit Protocol: INCORRECT_DECIMALS" if the LP token does not have 18 decimals. + * @throws "Unit Protocol: CURVE_INCORRECT_COINS_COUNT" if the Curve pool does not have any coins. + * @throws "Unit Protocol: ORACLE_NOT_FOUND" if an oracle for a coin is not found. + */ function assetToUsd(address asset, uint amount) public override view returns (uint) { if (amount == 0) return 0; ICurveRegistry cR = ICurveRegistry(curveProvider.get_registry()); @@ -67,4 +79,4 @@ contract CurveLPOracle is IOracleUsd { return amount.mul(price_q112); } -} +} \ No newline at end of file diff --git a/contracts/oracles/CyTokenOracle.sol b/contracts/oracles/CyTokenOracle.sol index a26aa30..e652947 100644 --- a/contracts/oracles/CyTokenOracle.sol +++ b/contracts/oracles/CyTokenOracle.sol @@ -10,40 +10,58 @@ import "../interfaces/IOracleRegistry.sol"; import "../interfaces/IOracleEth.sol"; import "../VaultParameters.sol"; -/** +/* * @title CyTokenOracle - * @dev Wrapper to quote cyToken assets like cyWETH, cyDAI, cyUSDT, cyUSDC - * @dev cyToken list: https://docs.cream.finance/iron-bank/iron-bank#yearn-token-cytoken - **/ - -contract CyTokenOracle is IOracleUsd, Auth { + * @dev Wrapper to quote cyToken assets like cyWETH, cyDAI, cyUSDT, cyUSDC. + * @dev cyToken list: https://docs.cream.finance/iron-bank/iron-bank#yearn-token-cytoken + */ +contract CyTokenOracle is IOracleUsd, Auth { using SafeMath for uint; uint constant expScale = 1e18; + // Mapping to track enabled cyToken implementations mapping (address => bool) public enabledImplementations; + // Oracle registry to fetch the current oracle for an asset IOracleRegistry public immutable oracleRegistry; + // Event emitted when a cyToken implementation is enabled or disabled event ImplementationChanged(address indexed implementation, bool enabled); + /** + * @dev Constructs the CyTokenOracle contract. + * @param _vaultParameters The address of the system's VaultParameters contract. + * @param _oracleRegistry The address of the OracleRegistry contract. + * @param impls An array of addresses of the initial cyToken implementations to enable. + */ constructor(address _vaultParameters, address _oracleRegistry, address[] memory impls) Auth(_vaultParameters) { require(_vaultParameters != address(0) && _oracleRegistry != address(0), "Unit Protocol: ZERO_ADDRESS"); oracleRegistry = IOracleRegistry(_oracleRegistry); for (uint i = 0; i < impls.length; i++) { - require(impls[i] != address(0), "Unit Protocol: ZERO_ADDRESS"); - enabledImplementations[impls[i]] = true; - emit ImplementationChanged(impls[i], true); + require(impls[i] != address(0), "Unit Protocol: ZERO_ADDRESS"); + enabledImplementations[impls[i]] = true; + emit ImplementationChanged(impls[i], true); } } + /** + * @dev Enables or disables a cyToken implementation. + * @param impl The address of the cyToken implementation. + * @param enable True to enable or false to disable the implementation. + */ function setImplementation(address impl, bool enable) external onlyManager { - require(impl != address(0), "Unit Protocol: ZERO_ADDRESS"); - enabledImplementations[impl] = enable; - emit ImplementationChanged(impl, enable); + require(impl != address(0), "Unit Protocol: ZERO_ADDRESS"); + enabledImplementations[impl] = enable; + emit ImplementationChanged(impl, enable); } - // returns Q112-encoded value + /** + * @dev Converts the amount of cyToken into the equivalent USD value encoded in Q112 format. + * @param bearing The address of the cyToken. + * @param amount The amount of cyToken to convert. + * @return The equivalent USD value encoded in Q112 format. + */ function assetToUsd(address bearing, uint amount) public override view returns (uint) { if (amount == 0) return 0; (address underlying, uint underlyingAmount) = bearingToUnderlying(bearing, amount); @@ -52,8 +70,15 @@ contract CyTokenOracle is IOracleUsd, Auth { return _oracleForUnderlying.assetToUsd(underlying, underlyingAmount); } - function bearingToUnderlying(address bearing, uint amount) public view returns (address, uint) { - address _underlying = IcyToken(bearing).underlying(); + /** + * @dev Converts the amount of cyToken into the underlying asset and its amount. + * @param bearing The address of the cyToken. + * @param amount The amount of cyToken to convert. + * @return _underlying The address of the underlying asset. + * @return _amount The amount of the underlying asset. + */ + function bearingToUnderlying(address bearing, uint amount) public view returns (address _underlying, uint _amount) { + _underlying = IcyToken(bearing).underlying(); require(_underlying != address(0), "Unit Protocol: UNDEFINED_UNDERLYING"); address _implementation = IcyToken(bearing).implementation(); require(enabledImplementations[_implementation], "Unit Protocol: UNSUPPORTED_CYTOKEN_IMPLEMENTATION"); @@ -63,4 +88,4 @@ contract CyTokenOracle is IOracleUsd, Auth { return (_underlying, amount.mul(_exchangeRateStored).div(expScale)); } -} +} \ No newline at end of file diff --git a/contracts/oracles/KeydonixOracleAbstract.sol b/contracts/oracles/KeydonixOracleAbstract.sol index b47c170..2e5f402 100644 --- a/contracts/oracles/KeydonixOracleAbstract.sol +++ b/contracts/oracles/KeydonixOracleAbstract.sol @@ -6,24 +6,35 @@ pragma solidity 0.7.6; pragma experimental ABIEncoderV2; - /** * @title KeydonixOracleAbstract - **/ + * @dev Abstract contract for Keydonix Oracle providing an interface to convert asset to USD value. + */ abstract contract KeydonixOracleAbstract { + /// @notice Constant used for decimal handling in calculations. uint public constant Q112 = 2 ** 112; + /** + * @dev Data structure representing the proof data required for price calculation. + */ struct ProofDataStruct { - bytes block; - bytes accountProofNodesRlp; - bytes reserveAndTimestampProofNodesRlp; - bytes priceAccumulatorProofNodesRlp; + bytes block; // RLP encoded block header data. + bytes accountProofNodesRlp; // RLP encoded account proof nodes. + bytes reserveAndTimestampProofNodesRlp; // RLP encoded reserve and timestamp proof nodes. + bytes priceAccumulatorProofNodesRlp; // RLP encoded price accumulator proof nodes. } + /** + * @notice Converts the amount of the asset into USD value based on the provided proof data. + * @param asset The address of the asset to be converted. + * @param amount The amount of the asset to be converted. + * @param proofData The proof data required for conversion. + * @return The USD value of the given amount of the asset. + */ function assetToUsd( address asset, uint amount, ProofDataStruct memory proofData ) public virtual view returns (uint); -} +} \ No newline at end of file diff --git a/contracts/oracles/OraclePoolToken.sol b/contracts/oracles/OraclePoolToken.sol index 1159b3c..ce401f1 100644 --- a/contracts/oracles/OraclePoolToken.sol +++ b/contracts/oracles/OraclePoolToken.sol @@ -12,11 +12,10 @@ import "../interfaces/IOracleUsd.sol"; import "../interfaces/IOracleRegistry.sol"; import "../interfaces/IToken.sol"; - /** * @title OraclePoolToken * @dev Calculates the USD price of Uniswap LP tokens - **/ + */ contract OraclePoolToken is IOracleUsd { using SafeMath for uint; @@ -26,6 +25,10 @@ contract OraclePoolToken is IOracleUsd { uint public immutable Q112 = 2 ** 112; + /** + * @notice Constructs the OraclePoolToken contract + * @param _oracleRegistry Address of the OracleRegistry contract + */ constructor(address _oracleRegistry) { oracleRegistry = IOracleRegistry(_oracleRegistry); WETH = IOracleRegistry(_oracleRegistry).WETH(); @@ -113,6 +116,12 @@ contract OraclePoolToken is IOracleUsd { return IOracleEth(oracleRegistry.oracleByAsset(WETH)).ethToUsd(priceInEth); } + /** + * @notice Calculates the square root of a given number + * @param x The number to calculate the square root of + * @return y The square root of the given number + * @dev Uses the Babylonian method (also known as Hero's method) for calculating square roots + */ function sqrt(uint x) internal pure returns (uint y) { if (x > 3) { uint z = x / 2 + 1; @@ -125,4 +134,4 @@ contract OraclePoolToken is IOracleUsd { y = 1; } } -} +} \ No newline at end of file diff --git a/contracts/oracles/OracleRegistry.sol b/contracts/oracles/OracleRegistry.sol index 8369235..aa6fc3c 100644 --- a/contracts/oracles/OracleRegistry.sol +++ b/contracts/oracles/OracleRegistry.sol @@ -8,6 +8,10 @@ pragma abicoder v2; import "../VaultParameters.sol"; +/** + * @title OracleRegistry + * @dev Contract that manages the registry of oracles for different asset types. + */ contract OracleRegistry is Auth { struct Oracle { @@ -45,6 +49,11 @@ contract OracleRegistry is Auth { _; } + /** + * @dev Constructor for OracleRegistry. + * @param vaultParameters The address of the VaultParameters contract. + * @param _weth The address of the wrapped ETH token. + */ constructor(address vaultParameters, address _weth) Auth(vaultParameters) validAddress(vaultParameters) @@ -53,6 +62,10 @@ contract OracleRegistry is Auth { WETH = _weth; } + /** + * @dev Sets the keydonix oracle types. + * @param _keydonixOracleTypes An array of oracle type IDs. + */ function setKeydonixOracleTypes(uint[] calldata _keydonixOracleTypes) public onlyManager { for (uint i = 0; i < _keydonixOracleTypes.length; i++) { require(_keydonixOracleTypes[i] != 0, "Unit Protocol: INVALID_TYPE"); @@ -64,6 +77,11 @@ contract OracleRegistry is Auth { emit KeydonixOracleTypes(); } + /** + * @dev Sets or updates the oracle for a given oracle type. + * @param oracleType The oracle type ID. + * @param oracle The oracle address. + */ function setOracle(uint oracleType, address oracle) public onlyManager validType(oracleType) @@ -89,6 +107,10 @@ contract OracleRegistry is Auth { emit OracleType(oracleType, oracle); } + /** + * @dev Unsets the oracle for a given oracle type. + * @param oracleType The oracle type ID to unset. + */ function unsetOracle(uint oracleType) public onlyManager validType(oracleType) validAddress(oracleByType[oracleType]) { address oracle = oracleByType[oracleType]; delete oracleByType[oracleType]; @@ -97,6 +119,11 @@ contract OracleRegistry is Auth { emit OracleType(oracleType, address(0)); } + /** + * @dev Sets the oracle type for a specific asset. + * @param asset The asset address. + * @param oracleType The oracle type ID. + */ function setOracleTypeForAsset(address asset, uint oracleType) public onlyManager validAddress(asset) @@ -107,12 +134,21 @@ contract OracleRegistry is Auth { emit AssetOracle(asset, oracleType); } + /** + * @dev Sets the oracle type for multiple assets. + * @param assets An array of asset addresses. + * @param oracleType The oracle type ID. + */ function setOracleTypeForAssets(address[] calldata assets, uint oracleType) public { for (uint i = 0; i < assets.length; i++) { setOracleTypeForAsset(assets[i], oracleType); } } + /** + * @dev Unsets the oracle type for a specific asset. + * @param asset The asset address to unset. + */ function unsetOracleForAsset(address asset) public onlyManager validAddress(asset) @@ -122,12 +158,20 @@ contract OracleRegistry is Auth { emit AssetOracle(asset, 0); } + /** + * @dev Unsets the oracle type for multiple assets. + * @param assets An array of asset addresses. + */ function unsetOracleForAssets(address[] calldata assets) public { for (uint i = 0; i < assets.length; i++) { unsetOracleForAsset(assets[i]); } } + /** + * @dev Retrieves all active oracles with their types. + * @return foundOracles An array of Oracle structs containing oracle types and addresses. + */ function getOracles() external view returns (Oracle[] memory foundOracles) { Oracle[] memory allOracles = new Oracle[](maxOracleType); @@ -147,10 +191,19 @@ contract OracleRegistry is Auth { } } + /** + * @dev Retrieves the keydonix oracle types. + * @return An array of keydonix oracle type IDs. + */ function getKeydonixOracleTypes() external view returns (uint[] memory) { return keydonixOracleTypes; } + /** + * @dev Retrieves the oracle address for a specific asset. + * @param asset The asset address. + * @return The address of the oracle associated with the asset. + */ function oracleByAsset(address asset) external view returns (address) { uint oracleType = oracleTypeByAsset[asset]; if (oracleType == 0) { @@ -159,4 +212,4 @@ contract OracleRegistry is Auth { return oracleByType[oracleType]; } -} +} \ No newline at end of file diff --git a/contracts/oracles/OracleSimple.sol b/contracts/oracles/OracleSimple.sol index ef9ed61..fc8c0ae 100644 --- a/contracts/oracles/OracleSimple.sol +++ b/contracts/oracles/OracleSimple.sol @@ -5,28 +5,51 @@ */ pragma solidity 0.7.6; - -/** +/* * @title OracleSimple - **/ + * @dev Abstract contract for defining the interface of an oracle that converts asset amounts to USD. + */ abstract contract OracleSimple { + /** + * @notice Convert an asset amount to USD + * @param asset The address of the asset to convert + * @param amount The amount of the asset to convert + * @return The equivalent amount in USD + */ function assetToUsd(address asset, uint amount) public virtual view returns (uint); } -/** +/* * @title OracleSimplePoolToken - **/ + * @dev Abstract contract for an oracle that uses a main asset oracle for pool tokens. + */ abstract contract OracleSimplePoolToken is OracleSimple { + // Reference to the main asset oracle ChainlinkedOracleSimple public oracleMainAsset; } -/** +/* * @title ChainlinkedOracleSimple - **/ + * @dev Abstract contract for an oracle using Chainlink to convert assets to USD or ETH. + */ abstract contract ChainlinkedOracleSimple is OracleSimple { + // Address of the WETH token address public WETH; + + /** + * @notice Convert an ETH amount to USD + * @param ethAmount The amount of ETH to convert + * @return The equivalent amount in USD + */ function ethToUsd(uint ethAmount) public virtual view returns (uint); + + /** + * @notice Convert an asset amount to ETH + * @param asset The address of the asset to convert + * @param amount The amount of the asset to convert + * @return The equivalent amount in ETH + */ function assetToEth(address asset, uint amount) public virtual view returns (uint); -} +} \ No newline at end of file diff --git a/contracts/oracles/WrappedToUnderlyingOracle.sol b/contracts/oracles/WrappedToUnderlyingOracle.sol index 506eb5a..2d91757 100644 --- a/contracts/oracles/WrappedToUnderlyingOracle.sol +++ b/contracts/oracles/WrappedToUnderlyingOracle.sol @@ -13,27 +13,47 @@ import "../interfaces/IOracleRegistry.sol"; /** * @title WrappedToUnderlyingOracle - * @dev Oracle to quote wrapped tokens to underlying - **/ + * @dev Oracle to quote wrapped tokens to underlying. This contract allows you to set and retrieve the underlying asset for a wrapped token, as well as to get the USD price of an asset. + */ contract WrappedToUnderlyingOracle is IOracleUsd, Auth { IOracleRegistry public immutable oracleRegistry; mapping (address => address) public assetToUnderlying; + /** + * @dev Emitted when a new underlying asset is set for a wrapped token. + * @param wrapped The address of the wrapped token. + * @param underlying The address of the underlying token. + */ event NewUnderlying(address indexed wrapped, address indexed underlying); + /** + * @dev Constructs the WrappedToUnderlyingOracle contract. + * @param _vaultParameters The address of the VaultParameters contract. + * @param _oracleRegistry The address of the OracleRegistry contract. + */ constructor(address _vaultParameters, address _oracleRegistry) Auth(_vaultParameters) { require(_vaultParameters != address(0) && _oracleRegistry != address(0), "Unit Protocol: ZERO_ADDRESS"); oracleRegistry = IOracleRegistry(_oracleRegistry); } + /** + * @dev Sets the underlying asset for a wrapped token. + * @param wrapped The address of the wrapped token. + * @param underlying The address of the underlying token. + */ function setUnderlying(address wrapped, address underlying) external onlyManager { assetToUnderlying[wrapped] = underlying; emit NewUnderlying(wrapped, underlying); } - // returns Q112-encoded value + /** + * @dev Returns the USD price of an asset as a Q112-encoded value. + * @param asset The address of the asset for which to get the USD price. + * @param amount The amount of the asset. + * @return The USD price of the given amount of the asset, Q112-encoded. + */ function assetToUsd(address asset, uint amount) public override view returns (uint) { if (amount == 0) return 0; @@ -42,6 +62,12 @@ contract WrappedToUnderlyingOracle is IOracleUsd, Auth { return IOracleUsd(oracle).assetToUsd(underlying, amount); } + /** + * @dev Internal function to get the oracle and underlying asset for a given asset. + * @param asset The address of the asset for which to get the oracle and underlying asset. + * @return oracle The address of the oracle for the underlying asset. + * @return underlying The address of the underlying asset. + */ function _getOracleAndUnderlying(address asset) internal view returns (address oracle, address underlying) { underlying = assetToUnderlying[asset]; @@ -50,5 +76,4 @@ contract WrappedToUnderlyingOracle is IOracleUsd, Auth { oracle = oracleRegistry.oracleByAsset(underlying); require(oracle != address(0), "Unit Protocol: NO_ORACLE_FOUND"); } - -} +} \ No newline at end of file diff --git a/contracts/oracles/WrappedToUnderlyingOracleKeydonix.sol b/contracts/oracles/WrappedToUnderlyingOracleKeydonix.sol index 9afeb55..6f7bdb5 100644 --- a/contracts/oracles/WrappedToUnderlyingOracleKeydonix.sol +++ b/contracts/oracles/WrappedToUnderlyingOracleKeydonix.sol @@ -12,27 +12,48 @@ import "../Auth2.sol"; /** * @title WrappedToUnderlyingOracleKeydonix - * @dev Oracle to quote wrapped tokens to underlying - **/ + * @dev Oracle to quote wrapped tokens to their underlying assets. + */ contract WrappedToUnderlyingOracleKeydonix is KeydonixOracleAbstract, Auth2 { + /// @notice Oracle registry to fetch the current oracle for an underlying asset. IOracleRegistry public immutable oracleRegistry; + /// @notice Mapping of wrapped tokens to their underlying tokens. mapping (address => address) public assetToUnderlying; + /// @notice Event emitted when a new underlying asset is set for a wrapped token. event NewUnderlying(address indexed wrapped, address indexed underlying); + /** + * @dev Constructor for WrappedToUnderlyingOracleKeydonix. + * @param _vaultParameters The address of the system's VaultParameters contract. + * @param _oracleRegistry The address of the OracleRegistry contract. + */ constructor(address _vaultParameters, address _oracleRegistry) Auth2(_vaultParameters) { require(_oracleRegistry != address(0), "Unit Protocol: ZERO_ADDRESS"); oracleRegistry = IOracleRegistry(_oracleRegistry); } + /** + * @notice Sets the underlying asset for a wrapped token. + * @dev Only callable by the manager role. + * @param wrapped The address of the wrapped token. + * @param underlying The address of the underlying token. + */ function setUnderlying(address wrapped, address underlying) external onlyManager { assetToUnderlying[wrapped] = underlying; emit NewUnderlying(wrapped, underlying); } - // returns Q112-encoded value + /** + * @notice Retrieves the USD value of the asset provided in the amount specified. + * @dev Returns a Q112-encoded value, which is a value shifted left by 112 bits to retain fractional precision. + * @param asset The address of the asset to be quoted. + * @param amount The amount of the asset to be quoted. + * @param proofData The proof data required for the oracle to function. + * @return The USD value of the asset amount provided, encoded in Q112 format. + */ function assetToUsd( address asset, uint amount, @@ -46,7 +67,11 @@ contract WrappedToUnderlyingOracleKeydonix is KeydonixOracleAbstract, Auth2 { } /** - * @dev for saving gas not checking underlying oracle for keydonix type since call to online oracle will fail anyway + * @dev Internal function to get the oracle and underlying asset for a wrapped token. + * @dev for saving gas not checking underlying oracle for keydonix type since call to online oracle will fail anyway + * @param asset The address of the wrapped token. + * @return oracle The oracle address for the underlying asset. + * @return underlying The underlying asset address. */ function _getOracleAndUnderlying(address asset) internal view returns (address oracle, address underlying) { underlying = assetToUnderlying[asset]; @@ -55,5 +80,4 @@ contract WrappedToUnderlyingOracleKeydonix is KeydonixOracleAbstract, Auth2 { oracle = oracleRegistry.oracleByAsset(underlying); require(oracle != address(0), "Unit Protocol: NO_ORACLE_FOUND"); } - -} +} \ No newline at end of file diff --git a/contracts/oracles/WstEthOracle.sol b/contracts/oracles/WstEthOracle.sol index b5d997c..1705b25 100644 --- a/contracts/oracles/WstEthOracle.sol +++ b/contracts/oracles/WstEthOracle.sol @@ -19,20 +19,33 @@ import "../VaultParameters.sol"; contract WstEthOracle is IOracleUsd, Auth { using SafeMath for uint; + // Oracle Registry contract address IOracleRegistry public immutable oracleRegistry; + // StETH price feed contract address address public stEthPriceFeed; + // StETH token decimals uint immutable stEthDecimals; + // wstETH token contract address address public immutable wstETH; + // Wrapped ETH token contract address address public immutable addressWETH; + // Maximum safe price deviation (in basis points) uint constant public MAX_SAFE_PRICE_DIFF = 500; + // Event emitted when stEthPriceFeed is changed event StEthPriceFeedChanged(address indexed implementation); + /* @notice Creates a WstEthOracle instance. + * @param _vaultParameters The address of the system's VaultParameters contract. + * @param _oracleRegistry The address of the OracleRegistry contract. + * @param _wstETH The address of the wstETH token contract. + * @param _stETHPriceFeed The address of the StETH price feed contract. + */ constructor(address _vaultParameters, address _oracleRegistry, address _wstETH, address _stETHPriceFeed) Auth(_vaultParameters) { require(_vaultParameters != address(0) && _oracleRegistry != address(0) && _wstETH != address(0) && _stETHPriceFeed != address(0), "Unit Protocol: ZERO_ADDRESS"); oracleRegistry = IOracleRegistry(_oracleRegistry); @@ -46,16 +59,27 @@ contract WstEthOracle is IOracleUsd, Auth { stEthDecimals = ERC20Like(stEthToken).decimals(); } + /* @notice Sets the StETH price feed contract address. + * @param impl The address of the new StETH price feed contract. + */ function setStEthPriceFeed(address impl) external onlyManager { require(impl != address(0), "Unit Protocol: ZERO_ADDRESS"); stEthPriceFeed = impl; emit StEthPriceFeedChanged(impl); } + /* @notice Returns the number of decimals of the StETH token. + * @return The number of decimals for StETH. + */ function getDecimalsStEth() public view returns (uint) { return stEthDecimals; } + /* @notice Calculates the percentage difference between two values. + * @param nv New value for comparison. + * @param ov Old value for comparison. + * @return The percentage difference (in basis points). + */ function _percentage_diff(uint nv, uint ov) private pure returns (uint) { if (nv > ov) { return ( nv - ov ) * 10000 / ov; @@ -64,11 +88,20 @@ contract WstEthOracle is IOracleUsd, Auth { } } + /* @notice Determines if the price has changed unsafely. + * @param pool_price The price from the liquidity pool. + * @param oracle_price The price from the oracle. + * @return True if the price difference exceeds the safe threshold. + */ function has_changed_unsafely(uint256 pool_price, uint256 oracle_price) private pure returns (bool) { return _percentage_diff(pool_price, oracle_price) > MAX_SAFE_PRICE_DIFF; } - // returns Q112-encoded value + /* @notice Converts wstETH to USD. + * @param bearing The address of the wstETH token contract. + * @param amount The amount of wstETH to convert. + * @return The equivalent USD value, Q112-encoded. + */ function assetToUsd(address bearing, uint amount) public override view returns (uint) { require(bearing == wstETH, "Unit Protocol: BEARING_IS_NOT_WSTETH"); if (amount == 0) return 0; @@ -82,5 +115,4 @@ contract WstEthOracle is IOracleUsd, Auth { require(address(_oracleForUnderlying) != address(0), "Unit Protocol: ORACLE_NOT_FOUND"); return _oracleForUnderlying.assetToUsd(addressWETH, underlyingAmount); } - -} +} \ No newline at end of file diff --git a/contracts/oracles/YvTokenOracle.sol b/contracts/oracles/YvTokenOracle.sol index 03a7093..0d6a5bc 100644 --- a/contracts/oracles/YvTokenOracle.sol +++ b/contracts/oracles/YvTokenOracle.sol @@ -12,21 +12,32 @@ import "../VaultParameters.sol"; /** * @title YvTokensOracle - * @dev Wrapper to quote V2 yVault Tokens like yvWETH, yvDAI, yvUSDC, yvUSDT + * @dev Wrapper to quote V2 yVault Tokens like yvWETH, yvDAI, yvUSDC, yvUSDT. * @dev yVault Tokens list: https://docs.yearn.finance/yearn-finance/yvaults/vault-tokens#v2-yvault-tokens - **/ - + */ contract YvTokenOracle is IOracleUsd, Auth { using SafeMath for uint; + /// @notice Address of the OracleRegistry contract IOracleRegistry public immutable oracleRegistry; + /** + * @dev Creates a YvTokenOracle instance. + * @param _vaultParameters The address of the VaultParameters contract. + * @param _oracleRegistry The address of the OracleRegistry contract. + */ constructor(address _vaultParameters, address _oracleRegistry) Auth(_vaultParameters) { require(_vaultParameters != address(0) && _oracleRegistry != address(0), "Unit Protocol: ZERO_ADDRESS"); oracleRegistry = IOracleRegistry(_oracleRegistry); } - // returns Q112-encoded value + /** + * @notice Converts the amount of the yVault bearing token to its USD value. + * @param bearing The address of the yVault bearing token. + * @param amount The amount of the bearing token. + * @return The USD value of the bearing token amount, encoded in Q112 format. + * @dev The function reverts if the underlying asset's oracle is not found. + */ function assetToUsd(address bearing, uint amount) public override view returns (uint) { if (amount == 0) return 0; (address underlying, uint underlyingAmount) = bearingToUnderlying(bearing, amount); @@ -35,6 +46,14 @@ contract YvTokenOracle is IOracleUsd, Auth { return _oracleForUnderlying.assetToUsd(underlying, underlyingAmount); } + /** + * @notice Converts the amount of the yVault bearing token to the underlying asset amount. + * @param bearing The address of the yVault bearing token. + * @param amount The amount of the bearing token. + * @return underlying The address of the underlying asset. + * @return The amount of the underlying asset. + * @dev The function reverts if the underlying asset is not defined or if the amount exceeds the total supply. + */ function bearingToUnderlying(address bearing, uint amount) public view returns (address, uint) { address _underlying = IyvToken(bearing).token(); require(_underlying != address(0), "Unit Protocol: UNDEFINED_UNDERLYING"); @@ -45,4 +64,4 @@ contract YvTokenOracle is IOracleUsd, Auth { return (_underlying, amount.mul(_pricePerShare).div(10**_decimals)); } -} +} \ No newline at end of file diff --git a/contracts/swappers/AbstractSwapper.sol b/contracts/swappers/AbstractSwapper.sol index 965400d..a8e1494 100644 --- a/contracts/swappers/AbstractSwapper.sol +++ b/contracts/swappers/AbstractSwapper.sol @@ -5,18 +5,17 @@ */ pragma solidity 0.7.6; - import "../interfaces/swappers/ISwapper.sol"; import "../helpers/ReentrancyGuard.sol"; import '../helpers/TransferHelper.sol'; import "../helpers/SafeMath.sol"; import "../Auth2.sol"; - import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** - * @dev base class for swappers, makes common checks - * @dev internal _swapUsdpToAsset and _swapAssetToUsdp must be overridden instead of external swapUsdpToAsset and swapAssetToUsdp + * @title AbstractSwapper + * @dev Abstract contract for creating swapper contracts that handle asset swaps with USDP. + * @dev Child classes must implement internal _swapUsdpToAsset and _swapAssetToUsdp functions. */ abstract contract AbstractSwapper is ISwapper, ReentrancyGuard, Auth2 { using TransferHelper for address; @@ -24,6 +23,11 @@ abstract contract AbstractSwapper is ISwapper, ReentrancyGuard, Auth2 { IERC20 public immutable USDP; + /** + * @dev Sets the USDP token address and initializes the Auth2 contract. + * @param _vaultParameters The address of the vault parameters contract. + * @param _usdp The address of the USDP token contract. + */ constructor(address _vaultParameters, address _usdp) Auth2(_vaultParameters) { require(_usdp != address(0), "Unit Protocol Swappers: ZERO_ADDRESS"); @@ -31,17 +35,35 @@ abstract contract AbstractSwapper is ISwapper, ReentrancyGuard, Auth2 { } /** - * @dev usdp already transferred to swapper + * @dev Internal function to swap USDP to another asset. + * @param _user The address of the user initiating the swap. + * @param _asset The address of the asset to swap to. + * @param _usdpAmount The amount of USDP to swap. + * @param _minAssetAmount The minimum amount of the asset expected to receive. + * @return swappedAssetAmount The amount of asset tokens swapped. */ function _swapUsdpToAsset(address _user, address _asset, uint256 _usdpAmount, uint256 _minAssetAmount) internal virtual returns (uint swappedAssetAmount); /** - * @dev asset already transferred to swapper + * @dev Internal function to swap an asset to USDP. + * @param _user The address of the user initiating the swap. + * @param _asset The address of the asset to swap from. + * @param _assetAmount The amount of the asset to swap. + * @param _minUsdpAmount The minimum amount of USDP expected to receive. + * @return swappedUsdpAmount The amount of USDP tokens swapped. */ function _swapAssetToUsdp(address _user, address _asset, uint256 _assetAmount, uint256 _minUsdpAmount) internal virtual returns (uint swappedUsdpAmount); + /** + * @dev Swaps USDP to another asset with a direct transfer. + * @param _user The address of the user initiating the swap. + * @param _asset The address of the asset to swap to. + * @param _usdpAmount The amount of USDP to swap. + * @param _minAssetAmount The minimum amount of the asset expected to receive. + * @return swappedAssetAmount The amount of asset tokens swapped. + */ function swapUsdpToAsset(address _user, address _asset, uint256 _usdpAmount, uint256 _minAssetAmount) external override returns (uint swappedAssetAmount) // nonReentrant in swapUsdpToAssetWithDirectSending { @@ -51,6 +73,14 @@ abstract contract AbstractSwapper is ISwapper, ReentrancyGuard, Auth2 { return swapUsdpToAssetWithDirectSending(_user, _asset, _usdpAmount, _minAssetAmount); } + /** + * @dev Swaps an asset to USDP and sends the USDP to the user. + * @param _user Address of the user initiating the swap. + * @param _asset Address of the asset to swap from. + * @param _assetAmount Amount of the asset to swap. + * @param _minUsdpAmount Minimum amount of USDP expected to receive. + * @return swappedUsdpAmount Amount of USDP tokens received from the swap. + */ function swapAssetToUsdp(address _user, address _asset, uint256 _assetAmount, uint256 _minUsdpAmount) external override returns (uint swappedUsdpAmount) // nonReentrant in swapAssetToUsdpWithDirectSending { @@ -60,6 +90,15 @@ abstract contract AbstractSwapper is ISwapper, ReentrancyGuard, Auth2 { return swapAssetToUsdpWithDirectSending(_user, _asset, _assetAmount, _minUsdpAmount); } + + /** + * @dev Swaps USDP to another asset with a direct transfer. + * @param _user The address of the user initiating the swap. + * @param _asset The address of the asset to swap to. + * @param _usdpAmount The amount of USDP to swap. + * @param _minAssetAmount The minimum amount of the asset expected to receive. + * @return swappedAssetAmount The amount of asset tokens swapped. + */ function swapUsdpToAssetWithDirectSending(address _user, address _asset, uint256 _usdpAmount, uint256 _minAssetAmount) public override nonReentrant returns (uint swappedAssetAmount) { @@ -70,6 +109,14 @@ abstract contract AbstractSwapper is ISwapper, ReentrancyGuard, Auth2 { require(swappedAssetAmount >= _minAssetAmount, "Unit Protocol Swapper: SWAPPED_AMOUNT_LESS_THAN_EXPECTED_MINIMUM"); } + /** + * @dev Swaps an asset to USDP with a direct transfer. + * @param _user The address of the user initiating the swap. + * @param _asset The address of the asset to swap from. + * @param _assetAmount The amount of the asset to swap. + * @param _minUsdpAmount The minimum amount of USDP expected to receive. + * @return swappedUsdpAmount The amount of USDP tokens swapped. + */ function swapAssetToUsdpWithDirectSending(address _user, address _asset, uint256 _assetAmount, uint256 _minUsdpAmount) public override nonReentrant returns (uint swappedUsdpAmount) { @@ -79,4 +126,34 @@ abstract contract AbstractSwapper is ISwapper, ReentrancyGuard, Auth2 { require(swappedUsdpAmount >= _minUsdpAmount, "Unit Protocol Swappers: SWAPPED_AMOUNT_LESS_THAN_EXPECTED_MINIMUM"); } -} + + /** + * @dev External function to swap USDP to another asset. USDP is transferred from the user. + * @param _user The address of the user initiating the swap. + * @param _asset The address of the asset to swap to. + * @param _usdpAmount The amount of USDP to swap. + * @param _minAssetAmount The minimum amount of the asset expected to receive. + * @return swappedAssetAmount The amount of asset tokens swapped. + */ + function swapUsdpToAsset(address _user, address _asset, uint256 _usdpAmount, uint256 _minAssetAmount) + external override returns (uint swappedAssetAmount) + { + address(USDP).safeTransferFrom(_user, address(this), _usdpAmount); + return swapUsdpToAssetWithDirectSending(_user, _asset, _usdpAmount, _minAssetAmount); + } + + /** + * @dev External function to swap an asset to USDP. The asset is transferred from the user. + * @param _user The address of the user initiating the swap. + * @param _asset The address of the asset to swap from. + * @param _assetAmount The amount of the asset to swap. + * @param _minUsdpAmount The minimum amount of USDP expected to receive. + * @return swappedUsdpAmount The amount of USDP tokens swapped. + */ + function swapAssetToUsdp(address _user, address _asset, uint256 _assetAmount, uint256 _minUsdpAmount) + external override returns (uint swappedUsdpAmount) + { + _asset.safeTransferFrom(_user, address(this), _assetAmount); + return swapAssetToUsdpWithDirectSending(_user, _asset, _assetAmount, _minUsdpAmount); + } +} \ No newline at end of file diff --git a/contracts/swappers/SwapperUniswapV2Lp.sol b/contracts/swappers/SwapperUniswapV2Lp.sol index 3c37a24..7622e44 100644 --- a/contracts/swappers/SwapperUniswapV2Lp.sol +++ b/contracts/swappers/SwapperUniswapV2Lp.sol @@ -21,7 +21,8 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** - * @dev swap usdp/any uniswapv2 lp + * @title SwapperUniswapV2Lp + * @dev Swapper contract for exchanging USDP with Uniswap V2 LP tokens. */ contract SwapperUniswapV2Lp is AbstractSwapper { using SafeMath for uint; @@ -32,6 +33,13 @@ contract SwapperUniswapV2Lp is AbstractSwapper { ISwapper public immutable wethSwapper; + /** + * @dev Creates a swapper for Uniswap V2 LP tokens. + * @param _vaultParameters The address of the system's VaultParameters contract. + * @param _weth The address of the WETH token. + * @param _usdp The address of the USDP token. + * @param _wethSwapper The address of the WETH swapper. + */ constructor( address _vaultParameters, address _weth, address _usdp, address _wethSwapper @@ -47,6 +55,12 @@ contract SwapperUniswapV2Lp is AbstractSwapper { wethSwapper = ISwapper(_wethSwapper); } + /** + * @notice Predicts the output amount of LP tokens when swapping USDP. + * @param _asset The address of the LP token. + * @param _usdpAmountIn The amount of USDP being swapped. + * @return predictedAssetAmount The predicted amount of LP tokens to be received. + */ function predictAssetOut(address _asset, uint256 _usdpAmountIn) external view override returns (uint predictedAssetAmount) { IUniswapV2PairFull pair = IUniswapV2PairFull(_asset); (uint256 pairWethId,,) = pair.getTokenInfo(WETH); @@ -72,6 +86,12 @@ contract SwapperUniswapV2Lp is AbstractSwapper { } } + /** + * @notice Predicts the output amount of USDP when swapping LP tokens. + * @param _asset The address of the LP token. + * @param _assetAmountIn The amount of LP tokens being swapped. + * @return predictedUsdpAmount The predicted amount of USDP to be received. + */ function predictUsdpOut(address _asset, uint256 _assetAmountIn) external view override returns (uint predictedUsdpAmount) { IUniswapV2PairFull pair = IUniswapV2PairFull(_asset); (uint256 pairWethId, uint pairTokenId,) = pair.getTokenInfo(WETH); @@ -90,6 +110,13 @@ contract SwapperUniswapV2Lp is AbstractSwapper { predictedUsdpAmount = wethSwapper.predictUsdpOut(WETH, wethAmount); } + /** + * @dev Internal function to swap USDP to LP tokens. + * @param _user The address of the user to send the LP tokens to. + * @param _asset The address of the LP token. + * @param _usdpAmount The amount of USDP being swapped. + * @return swappedAssetAmount The amount of LP tokens received. + */ function _swapUsdpToAsset(address _user, address _asset, uint256 _usdpAmount, uint256 /** _minAssetAmount */) internal override returns (uint swappedAssetAmount) { @@ -111,6 +138,13 @@ contract SwapperUniswapV2Lp is AbstractSwapper { swappedAssetAmount = pair.mint(_user); } + /** + * @dev Internal function to swap LP tokens to USDP. + * @param _user The address of the user to send the USDP to. + * @param _asset The address of the LP token. + * @param _assetAmount The amount of LP tokens being swapped. + * @return swappedUsdpAmount The amount of USDP received. + */ function _swapAssetToUsdp(address _user, address _asset, uint256 _assetAmount, uint256 /** _minUsdpAmount */) internal override returns (uint swappedUsdpAmount) { @@ -133,10 +167,19 @@ contract SwapperUniswapV2Lp is AbstractSwapper { address(USDP).safeTransfer(_user, swappedUsdpAmount); } + /** + * @dev Internal function to swap tokens within a Uniswap V2 pair. + * @param _pair The Uniswap V2 pair contract interface. + * @param _token The address of the token to swap from. + * @param _tokenId The ID of the token within the Uniswap V2 pair. + * @param _amount The amount of tokens to swap. + * @param _to The address to send the swapped tokens to. + * @return tokenAmount The amount of tokens received from the swap. + */ function _swapPairTokens(IUniswapV2PairFull _pair, address _token, uint _tokenId, uint _amount, address _to) internal returns (uint tokenAmount) { tokenAmount = _pair.calcAmountOutByTokenId(_tokenId, _amount); TransferHelper.safeTransfer(_token, address(_pair), _amount); _pair.swap(_tokenId == 0 ? 0: tokenAmount, _tokenId == 1 ? 0 : tokenAmount, _to, new bytes(0)); } -} +} \ No newline at end of file diff --git a/contracts/swappers/SwapperWethViaCurve.sol b/contracts/swappers/SwapperWethViaCurve.sol index 5c27269..5a4df1b 100644 --- a/contracts/swappers/SwapperWethViaCurve.sol +++ b/contracts/swappers/SwapperWethViaCurve.sol @@ -21,7 +21,8 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** - * @dev swap usdp/weth + * @title SwapperWethViaCurve + * @dev This contract provides functionality to swap USDP for WETH and vice versa using Curve finance. */ contract SwapperWethViaCurve is AbstractSwapper { using SafeMath for uint; @@ -40,7 +41,15 @@ contract SwapperWethViaCurve is AbstractSwapper { uint256 public immutable TRICRYPTO2_USDT; uint256 public immutable TRICRYPTO2_WETH; - + /** + * @notice Creates a new SwapperWethViaCurve contract. + * @param _vaultParameters The address of the VaultParameters contract. + * @param _weth The address of the WETH token contract. + * @param _usdp The address of the USDP token contract. + * @param _usdt The address of the USDT token contract. + * @param _usdp3crvPool The address of the Curve USDP-3CRV pool. + * @param _tricrypto2Pool The address of the Curve TriCrypto2 pool. + */ constructor( address _vaultParameters, address _weth, address _usdp, address _usdt, address _usdp3crvPool, address _tricrypto2Pool @@ -73,6 +82,12 @@ contract SwapperWethViaCurve is AbstractSwapper { _usdt.safeApprove(_usdp3crvPool, type(uint256).max); } + /** + * @notice Predicts the amount of WETH that will be received for a given amount of USDP. + * @param _asset The address of the asset to predict the output for, must be WETH. + * @param _usdpAmountIn The amount of USDP to swap. + * @return predictedAssetAmount The predicted amount of WETH to be received. + */ function predictAssetOut(address _asset, uint256 _usdpAmountIn) external view override returns (uint predictedAssetAmount) { require(_asset == address(WETH), "Unit Protocol Swappers: UNSUPPORTED_ASSET"); @@ -84,7 +99,10 @@ contract SwapperWethViaCurve is AbstractSwapper { } /** - * @dev calculates with some small (~0.005%) error bcs of approximate calculations of fee in get_dy_underlying + * @notice Predicts the amount of USDP that will be received for a given amount of WETH. + * @param _asset The address of the asset to predict the output for, must be WETH. + * @param _assetAmountIn The amount of WETH to swap. + * @return predictedUsdpAmount The predicted amount of USDP to be received. */ function predictUsdpOut(address _asset, uint256 _assetAmountIn) external view override returns (uint predictedUsdpAmount) { require(_asset == address(WETH), "Unit Protocol Swappers: UNSUPPORTED_ASSET"); @@ -96,6 +114,13 @@ contract SwapperWethViaCurve is AbstractSwapper { predictedUsdpAmount = USDP_3CRV_POOL.get_dy_underlying(USDP_3CRV_POOL_USDT, USDP_3CRV_POOL_USDP, usdtAmount); } + /** + * @dev Executes the swap from USDP to WETH. + * @param _user The address of the user to send the swapped WETH to. + * @param _asset The address of the asset to swap, must be WETH. + * @param _usdpAmount The amount of USDP to swap. + * @return swappedAssetAmount The amount of WETH received from the swap. + */ function _swapUsdpToAsset(address _user, address _asset, uint256 _usdpAmount, uint256 /** _minAssetAmount */) internal override returns (uint swappedAssetAmount) { @@ -112,6 +137,13 @@ contract SwapperWethViaCurve is AbstractSwapper { address(WETH).safeTransfer(_user, swappedAssetAmount); } + /** + * @dev Executes the swap from WETH to USDP. + * @param _user The address of the user to send the swapped USDP to. + * @param _asset The address of the asset to swap, must be WETH. + * @param _assetAmount The amount of WETH to swap. + * @return swappedUsdpAmount The amount of USDP received from the swap. + */ function _swapAssetToUsdp(address _user, address _asset, uint256 _assetAmount, uint256 /** _minUsdpAmount */) internal override returns (uint swappedUsdpAmount) { @@ -127,4 +159,4 @@ contract SwapperWethViaCurve is AbstractSwapper { // USDP -> user address(USDP).safeTransfer(_user, swappedUsdpAmount); } -} +} \ No newline at end of file diff --git a/contracts/swappers/SwappersRegistry.sol b/contracts/swappers/SwappersRegistry.sol index 475a3ca..bdd0dfd 100644 --- a/contracts/swappers/SwappersRegistry.sol +++ b/contracts/swappers/SwappersRegistry.sol @@ -9,7 +9,11 @@ import "../interfaces/swappers/ISwapper.sol"; import "../interfaces/swappers/ISwappersRegistry.sol"; import "../Auth2.sol"; - +/** + * @title SwappersRegistry + * @dev Contract to manage a registry of swappers for Unit Protocol. + * Inherits from ISwappersRegistry and Auth2 for swapper interface and authorization respectively. + */ contract SwappersRegistry is ISwappersRegistry, Auth2 { struct SwapperInfo { @@ -20,30 +24,64 @@ contract SwappersRegistry is ISwappersRegistry, Auth2 { mapping(ISwapper => SwapperInfo) internal swappersInfo; ISwapper[] internal swappers; + /** + * @dev Initializes the contract by setting vault parameters and invoking Auth2 constructor. + * @param _vaultParameters The address of the vault parameters contract. + */ constructor(address _vaultParameters) Auth2(_vaultParameters) {} + /** + * @dev Returns the number of swappers registered. + * @return The number of registered swappers. + */ function getSwappersLength() external view override returns (uint) { return swappers.length; } + /** + * @dev Retrieves the ID of a specific swapper. + * @param _swapper The address of the swapper to query. + * @return The ID of the swapper. + * @notice Throws if the swapper does not exist. + */ function getSwapperId(ISwapper _swapper) external view override returns (uint) { require(hasSwapper(_swapper), "Unit Protocol Swappers: SWAPPER_IS_NOT_EXIST"); return uint(swappersInfo[_swapper].id); } + /** + * @dev Retrieves the swapper address by ID. + * @param _id The ID of the swapper to query. + * @return The address of the swapper with the given ID. + */ function getSwapper(uint _id) external view override returns (ISwapper) { return swappers[_id]; } + /** + * @dev Checks if a swapper is registered. + * @param _swapper The address of the swapper to check. + * @return True if the swapper exists, false otherwise. + */ function hasSwapper(ISwapper _swapper) public view override returns (bool) { return swappersInfo[_swapper].exists; } + /** + * @dev Retrieves the list of all registered swappers. + * @return An array of addresses of the registered swappers. + */ function getSwappers() external view override returns (ISwapper[] memory) { return swappers; } + /** + * @dev Registers a new swapper. + * @param _swapper The address of the swapper to register. + * @notice Only callable by the manager role. + * @notice Throws if the swapper address is zero or if the swapper is already registered. + */ function add(ISwapper _swapper) public onlyManager { require(address(_swapper) != address(0), "Unit Protocol Swappers: ZERO_ADDRESS"); require(!hasSwapper(_swapper), "Unit Protocol Swappers: SWAPPER_ALREADY_EXISTS"); @@ -54,6 +92,12 @@ contract SwappersRegistry is ISwappersRegistry, Auth2 { emit SwapperAdded(_swapper); } + /** + * @dev Unregisters a swapper. + * @param _swapper The address of the swapper to unregister. + * @notice Only callable by the manager role. + * @notice Throws if the swapper address is zero or if the swapper does not exist. + */ function remove(ISwapper _swapper) public onlyManager { require(address(_swapper) != address(0), "Unit Protocol Swappers: ZERO_ADDRESS"); require(hasSwapper(_swapper), "Unit Protocol Swappers: SWAPPER_IS_NOT_EXIST"); @@ -71,4 +115,4 @@ contract SwappersRegistry is ISwappersRegistry, Auth2 { emit SwapperRemoved(_swapper); } -} +} \ No newline at end of file diff --git a/contracts/swappers/helpers/CurveHelper.sol b/contracts/swappers/helpers/CurveHelper.sol index 3487496..fd4ef80 100644 --- a/contracts/swappers/helpers/CurveHelper.sol +++ b/contracts/swappers/helpers/CurveHelper.sol @@ -8,10 +8,25 @@ pragma solidity 0.7.6; import "../../interfaces/ICurvePool.sol"; import "../../interfaces/curve/ICurvePoolMeta.sol"; +/** + * @title CurveHelper Library + * @notice Provides functions for interacting with Curve Finance pools. It facilitates the retrieval of coin indices + * in Curve pools and meta pools, alongside ensuring minimal gas usage and handling of exceptional scenarios. + * @dev Assumes compliance with standard Curve pool interface. Functions are view-only but may revert on errors. + */ library CurveHelper { + /// @notice The maximum number of coins supported by the Curve pool int128 public constant MAX_COINS = 30; + /** + * @notice Gets the index of a coin in a Curve meta pool + * @param _pool The Curve meta pool + * @param _coin The address of the coin + * @return The index of the coin in the meta pool + * @dev Iterates through coins in the meta pool and its base pool to find the index + * @dev Throws if the pool is broken or the coin is not found + */ function getCoinIndexInMetaPool(ICurvePoolMeta _pool, address _coin) internal view returns (int128) { int128 basePoolIndex = 0; for (int128 i=0; i < MAX_COINS; i++) { @@ -34,6 +49,14 @@ library CurveHelper { return coinIndex; } + /** + * @notice Gets the index of a coin in a Curve pool + * @param _pool The Curve pool + * @param _coin The address of the coin + * @return The index of the coin in the pool + * @dev Iterates through coins in the pool to find the index + * @dev Reverts if the coin is not found in the pool + */ function getCoinIndexInPool(ICurvePool _pool, address _coin) internal view returns (int128) { for (int128 i=0; i < MAX_COINS; i++) { address coin = tryGetCoin(_pool, i); @@ -47,6 +70,13 @@ library CurveHelper { revert("Unit Protocol Swappers: COIN_NOT_FOUND_IN_POOL"); } + /** + * @notice Tries to get the address of a coin in a pool at a specific index + * @param _pool The Curve pool + * @param i The index of the coin + * @return The address of the coin at the given index or address(0) if not successful + * @dev Uses a low-level staticcall with limited gas to fetch the coin address + */ function tryGetCoin(ICurvePool _pool, int128 i) private view returns (address) { (bool success, bytes memory data) = address(_pool).staticcall{gas:20000}(abi.encodeWithSignature("coins(uint256)", uint(i))); if (!success || data.length != 32) { @@ -56,9 +86,15 @@ library CurveHelper { return bytesToAddress(data); } + /** + * @notice Converts bytes to an address + * @param _bytes The bytes to convert + * @return addr The converted address + * @dev Assumes that the input bytes are at least 32 bytes long + */ function bytesToAddress(bytes memory _bytes) private pure returns (address addr) { assembly { addr := mload(add(_bytes, 32)) } } -} +} \ No newline at end of file diff --git a/contracts/swappers/helpers/UniswapV2Helper.sol b/contracts/swappers/helpers/UniswapV2Helper.sol index dba6471..d8d5564 100644 --- a/contracts/swappers/helpers/UniswapV2Helper.sol +++ b/contracts/swappers/helpers/UniswapV2Helper.sol @@ -14,6 +14,8 @@ import "../../helpers/Math.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** + * @title UniswapV2Helper + * @dev Library providing functions to interact with UniswapV2 protocol. * @dev several methods for calculations different uniswap v2 params. Part of them extracted for uniswap contracts * @dev for original licenses see attached links */ @@ -21,8 +23,12 @@ library UniswapV2Helper { using SafeMath for uint; /** - * given some amount of an asset and pair reserves, returns an equivalent amount of the other asset + * @notice Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset. * see https://github.com/Uniswap/v2-periphery/blob/master/contracts/libraries/UniswapV2Library.sol + * @param amountA The amount of the first asset. + * @param reserveA The reserve of the first asset in the pair. + * @param reserveB The reserve of the second asset in the pair. + * @return amountB The equivalent amount of the second asset. */ function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) { require(amountA > 0, 'Unit Protocol Swappers: INSUFFICIENT_AMOUNT'); @@ -31,8 +37,12 @@ library UniswapV2Helper { } /** - * given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset + * @notice Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset. * see https://github.com/Uniswap/v2-periphery/blob/master/contracts/libraries/UniswapV2Library.sol + * @param amountIn The amount of the input asset. + * @param reserveIn The reserve of the input asset. + * @param reserveOut The reserve of the output asset. + * @return amountOut The maximum output amount of the output asset. */ function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) { require(amountIn > 0, 'Unit Protocol Swappers: INSUFFICIENT_INPUT_AMOUNT'); @@ -44,7 +54,12 @@ library UniswapV2Helper { } /** + * @notice Calculates the amount of LP tokens added during the fee minting process. * see pair._mintFee in pair contract https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol + * @param pair The UniswapV2 pair contract. + * @param _reserve0 The reserve of the first token. + * @param _reserve1 The reserve of the second token. + * @return The amount of LP tokens added during fee minting. */ function getLPAmountAddedDuringFeeMint(IUniswapV2PairFull pair, uint _reserve0, uint _reserve1) internal view returns (uint) { address feeTo = IUniswapV2Factory(pair.factory()).feeTo(); @@ -68,13 +83,27 @@ library UniswapV2Helper { } /** + * @notice Calculates the amount of LP tokens that will be received after depositing tokens to the pool. * see pair.mint in pair contract https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol + * @param _pair The UniswapV2 pair contract. + * @param _amount0 The amount of the first token being deposited. + * @param _amount1 The amount of the second token being deposited. + * @return The amount of LP tokens that will be received. */ function calculateLpAmountAfterDepositTokens(IUniswapV2PairFull _pair, uint _amount0, uint _amount1) internal view returns (uint) { (uint112 reserve0, uint112 reserve1,) = _pair.getReserves(); return calculateLpAmountAfterDepositTokens(_pair, _amount0, _amount1, reserve0, reserve1); } + /** + * @notice Calculates the amount of LP tokens that will be received after depositing tokens to the pool with specific reserves. + * @param _pair The UniswapV2 pair contract. + * @param _amount0 The amount of the first token being deposited. + * @param _amount1 The amount of the second token being deposited. + * @param _reserve0 The reserve of the first token. + * @param _reserve1 The reserve of the second token. + * @return The amount of LP tokens that will be received. + */ function calculateLpAmountAfterDepositTokens( IUniswapV2PairFull _pair, uint _amount0, uint _amount1, uint _reserve0, uint _reserve1 ) internal view returns (uint) { @@ -87,7 +116,12 @@ library UniswapV2Helper { } /** + * @notice Calculates the token amounts that will be received after withdrawing LP tokens from the pool. * see pair.burn in pair contract https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol + * @param pair The UniswapV2 pair contract. + * @param lpAmount The amount of LP tokens being withdrawn. + * @return amount0 The amount of the first token that will be received. + * @return amount1 The amount of the second token that will be received. */ function calculateTokensAmountAfterWithdrawLp(IUniswapV2PairFull pair, uint lpAmount) internal view returns (uint amount0, uint amount1) { (uint112 _reserve0, uint112 _reserve1,) = pair.getReserves(); @@ -101,6 +135,14 @@ library UniswapV2Helper { amount1 = lpAmount.mul(balance1) / _totalSupply; } + /** + * @notice Retrieves token information for a UniswapV2 pair given a token address. + * @param pair The UniswapV2 pair contract. + * @param _token The address of the token for which information is needed. + * @return tokenId The ID of the token in the pair (0 or 1). + * @return secondTokenId The ID of the other token in the pair (0 or 1). + * @return secondToken The address of the other token in the pair. + */ function getTokenInfo(IUniswapV2PairFull pair, address _token) internal view returns (uint tokenId, uint secondTokenId, address secondToken) { if (pair.token0() == _token) { return (0, 1, pair.token1()); @@ -111,12 +153,27 @@ library UniswapV2Helper { } } + /** + * @notice Calculates the output amount of a token swap given the token ID and amount. + * @param _pair The UniswapV2 pair contract. + * @param _tokenId The ID of the token being swapped. + * @param _amount The amount of the token being swapped. + * @return The output amount of the token swap. + */ function calcAmountOutByTokenId(IUniswapV2PairFull _pair, uint _tokenId, uint _amount) internal view returns (uint) { (uint112 reserve0, uint112 reserve1, ) = _pair.getReserves(); return calcAmountOutByTokenId(_pair, _tokenId, _amount, uint(reserve0), uint(reserve1)); } + /** + * @notice Calculates the output amount of a token swap given the token ID, amount and specific reserves. + * @param _tokenId The ID of the token being swapped. + * @param _amount The amount of the token being swapped. + * @param reserve0 The reserve of the first token. + * @param reserve1 The reserve of the second token. + * @return The output amount of the token swap. + */ function calcAmountOutByTokenId(IUniswapV2PairFull /* _pair */, uint _tokenId, uint _amount, uint reserve0, uint reserve1) internal pure returns (uint) { uint256 reserveIn; uint256 reserveOut; @@ -132,9 +189,11 @@ library UniswapV2Helper { } /** - * @dev In case we want to get pair LP tokens but we have weth only - * @dev - First we swap `wethToSwap` tokens - * @dev - then we deposit `_wethAmount-wethToSwap` and `exchangedTokenAmount` to pair + * @notice Calculates the amount of WETH to swap before minting LP tokens when only WETH is available. + * @param _pair The UniswapV2 pair contract. + * @param _wethAmount The total amount of WETH available for swapping and adding liquidity. + * @param _pairWethId The ID of WETH in the UniswapV2 pair. + * @return wethToSwap The amount of WETH to swap to balance the token amounts for adding liquidity. */ function calcWethToSwapBeforeMint(IUniswapV2PairFull _pair, uint _wethAmount, uint _pairWethId) internal view returns (uint wethToSwap) { (uint112 reserve0, uint112 reserve1, ) = _pair.getReserves(); @@ -194,4 +253,4 @@ library UniswapV2Helper { result = sqrt(wethReserve*(3988009*wethReserve + 3988000*wethAmount))/1994 - (1997*wethReserve)/1994 */ } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/ChainlinkAggregator_Mock.sol b/contracts/test-helpers/ChainlinkAggregator_Mock.sol index b5fa46a..0284829 100644 --- a/contracts/test-helpers/ChainlinkAggregator_Mock.sol +++ b/contracts/test-helpers/ChainlinkAggregator_Mock.sol @@ -5,20 +5,42 @@ */ pragma solidity 0.7.6; +/** + * @title ChainlinkAggregator_Mock + * @dev Mock contract for Chainlink Aggregator used for testing purposes. + */ contract ChainlinkAggregator_Mock { + // Latest price answer provided by the oracle int public latestAnswer; + + // Timestamp of the latest price update uint public latestTimestamp = block.timestamp; + + // Number of decimals the answer is in uint public decimals; + // Address of the contract admin address admin = msg.sender; + // Event emitted when the price is updated event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp); + /** + * @dev Constructor sets the initial price and decimals. + * @param price Initial price to set. + * @param _decimals Number of decimals the price is in. + */ constructor (int price, uint _decimals) { latestAnswer = price; decimals = _decimals; } + /** + * @dev Allows the admin to update the price. + * @param price New price to be set. + * @notice Emits the AnswerUpdated event. + * @throws if the caller is not the admin. + */ function setPrice(int price) external { require(msg.sender == admin, "Unit Protocol: UNAUTHORIZED"); latestAnswer = price; @@ -26,6 +48,14 @@ contract ChainlinkAggregator_Mock { emit AnswerUpdated(int(price), block.timestamp, block.timestamp); } + /** + * @dev Provides the latest price data. + * @return roundId The round ID of the latest update (always 0 for mock). + * @return answer The latest price answer. + * @return startedAt The timestamp when the round started (always 0 for mock). + * @return updatedAt The timestamp of the latest price update. + * @return answeredInRound The round ID when the given answer was provided (always 0 for mock). + */ function latestRoundData() external view @@ -43,4 +73,4 @@ contract ChainlinkAggregator_Mock { startedAt = 0; answeredInRound = 0; } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/ChainlinkOracleMainAsset_Mock.sol b/contracts/test-helpers/ChainlinkOracleMainAsset_Mock.sol index ca68a6c..30b1532 100644 --- a/contracts/test-helpers/ChainlinkOracleMainAsset_Mock.sol +++ b/contracts/test-helpers/ChainlinkOracleMainAsset_Mock.sol @@ -12,19 +12,31 @@ import "../interfaces/IERC20WithOptional.sol"; import "../VaultParameters.sol"; import "../oracles/OracleSimple.sol"; - /** * @title ChainlinkOracleMainAsset_Mock - * @dev Calculates the USD price of desired tokens - **/ + * @dev Mock contract to calculate the USD price of desired tokens using Chainlink oracles. + */ contract ChainlinkOracleMainAsset_Mock is ChainlinkedOracleSimple, Auth { using SafeMath for uint; + // Mapping of token addresses to their respective USD Chainlink Price Feed aggregators mapping (address => address) public usdAggregators; + + // Mapping of token addresses to their respective ETH Chainlink Price Feed aggregators mapping (address => address) public ethAggregators; + // Constant to scale asset price uint public constant Q112 = 2 ** 112; + /** + * @notice Constructor sets initial aggregators for tokens + * @param tokenAddresses1 Array of token addresses for which USD aggregators are being set + * @param _usdAggregators Array of Chainlink USD aggregator addresses corresponding to token addresses + * @param tokenAddresses2 Array of token addresses for which ETH aggregators are being set + * @param _ethAggregators Array of Chainlink ETH aggregator addresses corresponding to token addresses + * @param weth Address of the Wrapped Ether token + * @param vaultParameters Address of the VaultParameters contract + */ constructor( address[] memory tokenAddresses1, address[] memory _usdAggregators, @@ -51,6 +63,13 @@ contract ChainlinkOracleMainAsset_Mock is ChainlinkedOracleSimple, Auth { } } + /** + * @notice Sets or updates the USD and ETH aggregators for the given tokens + * @param tokenAddresses1 Array of token addresses for which USD aggregators are being set or updated + * @param _usdAggregators Array of new Chainlink USD aggregator addresses + * @param tokenAddresses2 Array of token addresses for which ETH aggregators are being set or updated + * @param _ethAggregators Array of new Chainlink ETH aggregator addresses + */ function setAggregators( address[] calldata tokenAddresses1, address[] calldata _usdAggregators, @@ -70,11 +89,12 @@ contract ChainlinkOracleMainAsset_Mock is ChainlinkedOracleSimple, Auth { } /** - * @notice {asset}/USD or {asset}/ETH pair must be registered at Chainlink + * @notice Converts the amount of the given asset to its equivalent in USD + * @dev The {asset}/USD or {asset}/ETH pair must be registered at Chainlink * @param asset The token address - * @param amount Amount of tokens - * @return The price of asset amount in USD - **/ + * @param amount The amount of tokens to convert + * @return The equivalent amount of the asset in USD + */ function assetToUsd(address asset, uint amount) public override view returns (uint) { if (amount == 0) { return 0; @@ -85,6 +105,12 @@ contract ChainlinkOracleMainAsset_Mock is ChainlinkedOracleSimple, Auth { return ethToUsd(assetToEth(asset, amount)); } + /** + * @dev Internal function to convert the amount of the given asset to its equivalent in USD + * @param asset The token address + * @param amount The amount of tokens to convert + * @return The equivalent amount of the asset in USD + */ function _assetToUsd(address asset, uint amount) internal view returns (uint) { IAggregator agg = IAggregator(usdAggregators[asset]); (, int256 answer, , uint256 updatedAt, ) = agg.latestRoundData(); @@ -99,11 +125,12 @@ contract ChainlinkOracleMainAsset_Mock is ChainlinkedOracleSimple, Auth { } /** - * @notice {asset}/ETH pair must be registered at Chainlink + * @notice Converts the amount of the given asset to its equivalent in ETH + * @dev The {asset}/ETH pair must be registered at Chainlink * @param asset The token address - * @param amount Amount of tokens - * @return The price of asset amount in ETH - **/ + * @param amount The amount of tokens to convert + * @return The equivalent amount of the asset in ETH + */ function assetToEth(address asset, uint amount) public view override returns (uint) { if (amount == 0) { return 0; @@ -133,8 +160,9 @@ contract ChainlinkOracleMainAsset_Mock is ChainlinkedOracleSimple, Auth { /** * @notice ETH/USD price feed from Chainlink, see for more info: https://feeds.chain.link/eth-usd - * returns The price of given amount of Ether in USD (0 decimals) - **/ + * @param ethAmount The amount of Ether to convert + * @return The price of given amount of Ether in USD (0 decimals) + */ function ethToUsd(uint ethAmount) public override view returns (uint) { IAggregator agg = IAggregator(usdAggregators[WETH]); (, int256 answer, , uint256 updatedAt, ) = agg.latestRoundData(); @@ -142,10 +170,15 @@ contract ChainlinkOracleMainAsset_Mock is ChainlinkedOracleSimple, Auth { return ethAmount.mul(uint(answer)).div(10 ** agg.decimals()); } - function _usdToEth(uint ethAmount) internal view returns (uint) { + /** + * @dev Internal function to convert the given amount of USD to its equivalent in ETH + * @param usdAmount The amount of USD to convert + * @return The equivalent amount of USD in ETH + */ + function _usdToEth(uint usdAmount) internal view returns (uint) { IAggregator agg = IAggregator(usdAggregators[WETH]); (, int256 answer, , uint256 updatedAt, ) = agg.latestRoundData(); require(updatedAt > block.timestamp - 6 hours, "Unit Protocol: STALE_CHAINLINK_PRICE"); - return ethAmount.mul(10 ** agg.decimals()).div(uint(answer)); + return usdAmount.mul(10 ** agg.decimals()).div(uint(answer)); } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/CurveMock.sol b/contracts/test-helpers/CurveMock.sol index edfcacb..44f5403 100644 --- a/contracts/test-helpers/CurveMock.sol +++ b/contracts/test-helpers/CurveMock.sol @@ -5,47 +5,87 @@ */ pragma solidity 0.7.6; - +/** + * @title CurveProviderMock + * @dev Mock contract for Curve provider interactions. + */ contract CurveProviderMock { + // Address of the Curve registry contract. address public immutable get_registry; + /** + * @dev Constructs the CurveProviderMock contract. + * @param registry The address of the Curve registry contract. + */ constructor (address registry) { get_registry = registry; } } - +/** + * @title CurveRegistryMock + * @dev Mock contract for Curve registry interactions. + */ contract CurveRegistryMock { + // Mapping from LP token to the corresponding pool. mapping (address => address) public get_pool_from_lp_token; + // Internal mapping to store the number of coins for each pool. mapping (address => uint[2]) _get_n_coins; + /** + * @dev Constructs the CurveRegistryMock contract and initializes a pool with LP token and number of coins. + * @param lp The LP token address. + * @param pool The pool address. + * @param nCoins The number of coins in the pool. + */ constructor (address lp, address pool, uint nCoins) { setLP(lp, pool, nCoins); } + /** + * @dev Sets the LP token and pool information. + * @param lp The LP token address. + * @param pool The pool address. + * @param nCoins The number of coins in the pool. + */ function setLP(address lp, address pool, uint nCoins) public { get_pool_from_lp_token[lp] = pool; uint[2] memory nCoinsArray = [nCoins, nCoins]; _get_n_coins[pool] = nCoinsArray; } + /** + * @dev Retrieves the number of coins for a given pool. + * @param pool The pool address. + * @return An array with two elements, both representing the number of coins in the pool. + */ function get_n_coins(address pool) external view returns (uint[2] memory) { return _get_n_coins[pool]; } } - +/** + * @title CurvePool + * @dev Mock contract for Curve pool interactions. + */ contract CurvePool { + // The virtual price of the pool. uint public get_virtual_price; + // Mapping from index to coin addresses in the pool. mapping (uint => address) public coins; + /** + * @dev Sets the virtual price and coins of the pool. + * @param virtualPrice The virtual price to set for the pool. + * @param _coins The array of coin addresses to set for the pool. + */ function setPool(uint virtualPrice, address[] calldata _coins) public { get_virtual_price = virtualPrice; - for (uint i = 0; i < _coins.length; i ++) { + for (uint i = 0; i < _coins.length; i++) { coins[i] = _coins[i]; } } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/CyWETH.sol b/contracts/test-helpers/CyWETH.sol index d38850d..62ee158 100644 --- a/contracts/test-helpers/CyWETH.sol +++ b/contracts/test-helpers/CyWETH.sol @@ -7,15 +7,28 @@ pragma solidity 0.7.6; import "./EmptyToken.sol"; - +/* + * @title CyWETH + * @notice This contract extends EmptyToken to represent a tokenized position in Yearn Wrapped Ether. + */ contract CyWETH is EmptyToken { - address public underlying; + /* @notice The underlying asset of the Yearn Wrapped Ether. */ + address public underlying; - address public implementation; + /* @notice The address of the implementation contract. */ + address public implementation; - uint public exchangeRateStoredInternal; + /* @notice The stored exchange rate from the underlying to the Yearn Wrapped Ether. */ + uint public exchangeRateStoredInternal; + /* + * @dev Initializes the contract with the initial state. + * @param _totalSupply The initial total supply of the token. + * @param _underlying The address of the underlying asset. + * @param _implementation The address of the implementation contract. + * @param _exchangeRateStoredInternal The initial exchange rate from the underlying to the Yearn Wrapped Ether. + */ constructor( uint _totalSupply, address _underlying, @@ -29,13 +42,17 @@ contract CyWETH is EmptyToken { msg.sender ) { - underlying = _underlying; - implementation = _implementation; - exchangeRateStoredInternal = _exchangeRateStoredInternal; + underlying = _underlying; + implementation = _implementation; + exchangeRateStoredInternal = _exchangeRateStoredInternal; } + /* + * @notice Returns the stored exchange rate from the underlying to the Yearn Wrapped Ether. + * @return The current exchange rate as a uint. + */ function exchangeRateStored() public view returns (uint) { return exchangeRateStoredInternal; } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/DummyToken.sol b/contracts/test-helpers/DummyToken.sol index daaa535..d2f378d 100644 --- a/contracts/test-helpers/DummyToken.sol +++ b/contracts/test-helpers/DummyToken.sol @@ -7,9 +7,19 @@ pragma solidity 0.7.6; import "./EmptyToken.sol"; - +/** + * @title DummyToken + * @dev This contract extends the EmptyToken contract and allows the creation of a dummy token. + */ contract DummyToken is EmptyToken { + /** + * @dev Constructor for DummyToken. + * @param _name The name of the token. + * @param _symbol The symbol of the token. + * @param _decimals The number of decimals the token uses. + * @param _totalSupply The total supply of the token. + */ constructor( string memory _name, string memory _symbol, @@ -23,4 +33,4 @@ contract DummyToken is EmptyToken { msg.sender ) {} -} +} \ No newline at end of file diff --git a/contracts/test-helpers/EmptyToken.sol b/contracts/test-helpers/EmptyToken.sol index ec7c7b4..3bc5adf 100644 --- a/contracts/test-helpers/EmptyToken.sol +++ b/contracts/test-helpers/EmptyToken.sol @@ -13,6 +13,13 @@ contract EmptyToken is ERC20, IAssetTestsMint { event Burn(address indexed burner, uint value); + /** + * @dev Burns a specific amount of tokens from the caller. + * @param _value The amount of token to be burned. + * @return A boolean that indicates if the operation was successful. + * @notice This function decreases the total supply of tokens. + * @notice The caller must have a balance of at least `_value`. + */ function burn(uint _value) public returns (bool) { require(_value <= balanceOf(msg.sender), "BURN_INSUFFICIENT_BALANCE"); @@ -20,6 +27,14 @@ contract EmptyToken is ERC20, IAssetTestsMint { return true; } + /** + * @dev Burns a specific amount of tokens from the `_owner` on behalf of the caller. + * @param _owner The address of the token owner. + * @param _value The amount of token to be burned. + * @return A boolean that indicates if the operation was successful. + * @notice This function decreases the total supply of tokens. + * @notice The caller must have allowance for `_owner`'s tokens of at least `_value`. + */ function burnFrom(address _owner, uint _value) public returns (bool) { require(_owner != address(0), "ZERO_ADDRESS"); require(_value <= balanceOf(_owner), "BURNFROM_INSUFFICIENT_BALANCE"); @@ -29,6 +44,16 @@ contract EmptyToken is ERC20, IAssetTestsMint { return true; } + /** + * @dev Constructor to create a new EmptyToken + * @param _name Name of the new token. + * @param _symbol Symbol of the new token. + * @param _decimals Number of decimals of the new token. + * @param _totalSupply Initial total supply of tokens. + * @param _firstHolder Address that will receive the initial supply. + * @notice The `_firstHolder` cannot be the zero address. + * @notice The `_symbol` and `_name` are validated by `checkSymbolAndName`. + */ constructor( string memory _name, string memory _symbol, @@ -45,7 +70,13 @@ contract EmptyToken is ERC20, IAssetTestsMint { _mint(_firstHolder, _totalSupply); } - // Make sure symbol has 3-8 chars in [A-Za-z._] and name has up to 128 chars. + /** + * @dev Validates the symbol and name of the token. + * @param _symbol The symbol of the token. + * @param _name The name of the token. + * @notice The symbol must be 3-8 characters in `[A-Za-z._]`. + * @notice The name must be up to 128 characters and printable ASCII. + */ function checkSymbolAndName( string memory _symbol, string memory _name @@ -70,7 +101,13 @@ contract EmptyToken is ERC20, IAssetTestsMint { } } + /** + * @dev Mints tokens to the specified address. Can only be called by the contract owner. + * @param to The address that will receive the minted tokens. + * @param amount The amount of tokens to mint. + * @notice This function increases the total supply of tokens. + */ function tests_mint(address to, uint amount) public override { _mint(to, amount); } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/FoundationMock.sol b/contracts/test-helpers/FoundationMock.sol index 7fdcdca..bc51fd5 100644 --- a/contracts/test-helpers/FoundationMock.sol +++ b/contracts/test-helpers/FoundationMock.sol @@ -7,7 +7,15 @@ pragma solidity 0.7.6; import "../interfaces/IFoundation.sol"; - +/** + * @title FoundationMock + * @dev Mock implementation of the IFoundation interface for testing purposes. + */ contract FoundationMock is IFoundation { - function submitLiquidationFee(uint fee) external override {} -} + + /** + * @dev Submits the liquidation fee to the Foundation. + * @param fee The fee amount to be submitted. + */ + function submitLiquidationFee(uint fee) external override {} +} \ No newline at end of file diff --git a/contracts/test-helpers/IAssetTestsMint.sol b/contracts/test-helpers/IAssetTestsMint.sol index df2ba97..8575b09 100644 --- a/contracts/test-helpers/IAssetTestsMint.sol +++ b/contracts/test-helpers/IAssetTestsMint.sol @@ -5,6 +5,16 @@ */ pragma solidity ^0.7.6; +/** + * @title IAssetTestsMint + * @dev Interface for a contract that allows for minting of a particular asset. + */ interface IAssetTestsMint { + + /** + * @dev Mints the specified amount of the asset to the given user address. + * @param _user The address of the user to receive the minted assets. + * @param _amount The amount of the asset to be minted. + */ function tests_mint(address _user, uint _amount) external; -} +} \ No newline at end of file diff --git a/contracts/test-helpers/Keep3rOracleMainAsset_Mock.sol b/contracts/test-helpers/Keep3rOracleMainAsset_Mock.sol index 2d36a49..4ef54eb 100644 --- a/contracts/test-helpers/Keep3rOracleMainAsset_Mock.sol +++ b/contracts/test-helpers/Keep3rOracleMainAsset_Mock.sol @@ -14,8 +14,8 @@ import "../oracles/OracleSimple.sol"; /** * @title Keep3rOracleMainAsset_Mock - * @dev Calculates the USD price of desired tokens - **/ + * @dev Mock contract for calculating the USD price of desired tokens. This contract is for testing purposes only. + */ contract Keep3rOracleMainAsset_Mock is ChainlinkedOracleSimple { using SafeMath for uint; @@ -26,12 +26,17 @@ contract Keep3rOracleMainAsset_Mock is ChainlinkedOracleSimple { IUniswapV2Factory public immutable uniswapFactory; + /** + * @notice Creates a Keep3rOracleMainAsset_Mock contract. + * @param uniFactory The Uniswap V2 Factory address. + * @param weth The Wrapped Ether (WETH) token address. + * @param chainlinkAggregator The Chainlink aggregator address for ETH/USD price feed. + */ constructor( IUniswapV2Factory uniFactory, address weth, IAggregator chainlinkAggregator - ) - { + ) { require(address(uniFactory) != address(0), "Unit Protocol: ZERO_ADDRESS"); require(weth != address(0), "Unit Protocol: ZERO_ADDRESS"); require(address(chainlinkAggregator) != address(0), "Unit Protocol: ZERO_ADDRESS"); @@ -41,9 +46,14 @@ contract Keep3rOracleMainAsset_Mock is ChainlinkedOracleSimple { ethUsdChainlinkAggregator = chainlinkAggregator; } - // override with mock; only for tests - function assetToUsd(address asset, uint amount) public override view returns (uint) { - + /** + * @notice Converts the asset amount to its equivalent USD value. + * @param asset The address of the asset token. + * @param amount The amount of the asset to convert. + * @return usdValue The equivalent USD value of the input asset amount. + * @dev Override with mock; only for tests. This function is mocked for testing and should not be used for accurate pricing. + */ + function assetToUsd(address asset, uint amount) public override view returns (uint usdValue) { if (asset == WETH) { return ethToUsd(amount); } @@ -65,7 +75,14 @@ contract Keep3rOracleMainAsset_Mock is ChainlinkedOracleSimple { return ethToUsd(wethResult).mul(Q112).div(tokenReserve); } - function assetToEth(address asset, uint amount) public override view returns (uint) { + /** + * @notice Converts the asset amount to its equivalent ETH value. + * @param asset The address of the asset token. + * @param amount The amount of the asset to convert. + * @return ethValue The equivalent ETH value of the input asset amount. + * @dev This function is mocked for testing and should not be used for accurate pricing. + */ + function assetToEth(address asset, uint amount) public override view returns (uint ethValue) { if (asset == WETH) { return amount; } @@ -82,16 +99,18 @@ contract Keep3rOracleMainAsset_Mock is ChainlinkedOracleSimple { // WETH reserve of {Token}/WETH pool uint wethReserve = ERC20Like(WETH).balanceOf(uniswapPair); - return amount.mul(wethReserve).mul(Q112); + return amount.mul(wethReserve).mul(Q112).div(tokenReserve); } /** - * @notice ETH/USD price feed from Chainlink, see for more info: https://feeds.chain.link/eth-usd - * returns Price of given amount of Ether in USD (0 decimals) - **/ - function ethToUsd(uint ethAmount) public override view returns (uint) { + * @notice Retrieves the ETH/USD price from Chainlink, see for more info: https://feeds.chain.link/eth-usd + * @param ethAmount The amount of Ether to convert. + * @return usdValue The USD value of the input Ether amount. + * @dev Returns the price of the given amount of Ether in USD with 0 decimals. + */ + function ethToUsd(uint ethAmount) public override view returns (uint usdValue) { require(ethUsdChainlinkAggregator.latestTimestamp() > block.timestamp - 6 hours, "Unit Protocol: OUTDATED_CHAINLINK_PRICE"); uint ethUsdPrice = uint(ethUsdChainlinkAggregator.latestAnswer()); return ethAmount.mul(ethUsdPrice).div(ETH_USD_DENOMINATOR); } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/KeydonixOracleMainAsset_Mock.sol b/contracts/test-helpers/KeydonixOracleMainAsset_Mock.sol index 3e11c50..ec08811 100644 --- a/contracts/test-helpers/KeydonixOracleMainAsset_Mock.sol +++ b/contracts/test-helpers/KeydonixOracleMainAsset_Mock.sol @@ -14,8 +14,8 @@ import "../helpers/IUniswapV2Factory.sol"; /** * @title KeydonixOracleMainAsset_Mock - * @dev Calculates the USD price of desired tokens - **/ + * @dev Mock contract for calculating the USD price of desired tokens for testing purposes. + */ contract KeydonixOracleMainAsset_Mock is ChainlinkedKeydonixOracleMainAssetAbstract { using SafeMath for uint; @@ -25,6 +25,12 @@ contract KeydonixOracleMainAsset_Mock is ChainlinkedKeydonixOracleMainAssetAbstr IUniswapV2Factory public immutable uniswapFactory; + /** + * @dev Constructs the KeydonixOracleMainAsset_Mock contract. + * @param uniFactory The address of the UniswapV2Factory contract. + * @param weth The address of the WETH token contract. + * @param chainlinkAggregator The address of the Chainlink aggregator contract for ETH/USD price feed. + */ constructor( IUniswapV2Factory uniFactory, address weth, @@ -40,7 +46,13 @@ contract KeydonixOracleMainAsset_Mock is ChainlinkedKeydonixOracleMainAssetAbstr ethUsdChainlinkAggregator = chainlinkAggregator; } - // override with mock; only for tests + /** + * @notice Mock implementation to get the USD price of an asset. + * @param asset The address of the asset token contract. + * @param amount The amount of the asset tokens. + * @param proofData The proof data struct (not used in mock). + * @return The price of the given amount of asset tokens in USD. + */ function assetToUsd(address asset, uint amount, ProofDataStruct memory proofData) public override view returns (uint) { if (asset == WETH) { @@ -59,13 +71,19 @@ contract KeydonixOracleMainAsset_Mock is ChainlinkedKeydonixOracleMainAssetAbstr return ethToUsd(assetToEth(asset, amount, proofData).div(tokenReserve)); } - // override with mock; only for tests + /** + * @notice Mock implementation to get the ETH price of an asset. + * @param asset The address of the asset token contract. + * @param amount The amount of the asset tokens. + * @param proofData The proof data struct (not used in mock). + * @return The price of the given amount of asset tokens in ETH. + */ function assetToEth(address asset, uint amount, ProofDataStruct memory proofData) public override view returns (uint) { address uniswapPair = uniswapFactory.getPair(asset, WETH); require(uniswapPair != address(0), "Unit Protocol: UNISWAP_PAIR_DOES_NOT_EXIST"); - proofData; + proofData; // This is to silence the unused variable warning without changing the function signature. // WETH reserve of {Token}/WETH pool uint wethReserve = ERC20Like(WETH).balanceOf(uniswapPair); @@ -74,12 +92,13 @@ contract KeydonixOracleMainAsset_Mock is ChainlinkedKeydonixOracleMainAssetAbstr } /** - * @notice ETH/USD price feed from Chainlink, see for more info: https://feeds.chain.link/eth-usd - * returns Price of given amount of Ether in USD (0 decimals) - **/ + * @notice Retrieves the price of ETH in USD from the Chainlink aggregator. + * @param ethAmount The amount of ETH to convert to USD. + * @return The price of the given amount of ETH in USD. + */ function ethToUsd(uint ethAmount) public override view returns (uint) { require(ethUsdChainlinkAggregator.latestTimestamp() > block.timestamp - 6 hours, "Unit Protocol: OUTDATED_CHAINLINK_PRICE"); uint ethUsdPrice = uint(ethUsdChainlinkAggregator.latestAnswer()); return ethAmount.mul(ethUsdPrice).div(ETH_USD_DENOMINATOR); } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/KeydonixOraclePoolToken_Mock.sol b/contracts/test-helpers/KeydonixOraclePoolToken_Mock.sol index c1e04c7..64790ff 100644 --- a/contracts/test-helpers/KeydonixOraclePoolToken_Mock.sol +++ b/contracts/test-helpers/KeydonixOraclePoolToken_Mock.sol @@ -13,21 +13,33 @@ import "../helpers/SafeMath.sol"; /** * @title KeydonixOraclePoolToken_Mock - * @dev Calculates the USD price of desired tokens - **/ + * @dev Mock contract for calculating the USD price of pool tokens in tests. + */ contract KeydonixOraclePoolToken_Mock is ChainlinkedKeydonixOraclePoolTokenAbstract { using SafeMath for uint; + /** + * @dev Constructor for KeydonixOraclePoolToken_Mock. + * @param _keydonixOracleMainAsset_Mock Address of the Keydonix Oracle Main Asset mock contract. + */ constructor(address _keydonixOracleMainAsset_Mock) { uniswapOracleMainAsset = ChainlinkedKeydonixOracleMainAssetAbstract(_keydonixOracleMainAsset_Mock); } - // override with mock; only for tests + /** + * @notice Converts an amount of asset into USD value based on the stored oracle prices. + * @dev Mock function for converting asset to USD. Overrides the base function for testing purposes. + * @param asset The address of the Uniswap V2 pair token to convert. + * @param amount The amount of the asset to convert. + * @param /* proofData */ This parameter is ignored in the mock implementation. + * @return uint The equivalent USD value of the given asset amount. + * @dev Throws if the provided asset is not a registered pair with WETH. + */ function assetToUsd(address asset, uint amount, ProofDataStruct memory /* proofData */) public override view returns (uint) { IUniswapV2PairFull pair = IUniswapV2PairFull(asset); - uint ePool; // current WETH pool + uint ePool; // Current WETH pool (uint112 _reserve0, uint112 _reserve1,) = pair.getReserves(); @@ -43,4 +55,4 @@ contract KeydonixOraclePoolToken_Mock is ChainlinkedKeydonixOraclePoolTokenAbstr return uniswapOracleMainAsset.ethToUsd(totalValueInEth_q112); } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/KeydonixSimpleOracle_Mock.sol b/contracts/test-helpers/KeydonixSimpleOracle_Mock.sol index 75c483e..1493f97 100644 --- a/contracts/test-helpers/KeydonixSimpleOracle_Mock.sol +++ b/contracts/test-helpers/KeydonixSimpleOracle_Mock.sol @@ -8,18 +8,28 @@ pragma experimental ABIEncoderV2; import "../oracles/KeydonixOracleAbstract.sol"; -/** - * @title KeydonixSimpleOracle_Mock - * @dev Used in tests - **/ +/* @title KeydonixSimpleOracle_Mock + * @dev Mock implementation of the KeydonixOracleAbstract used for testing purposes. + */ contract KeydonixSimpleOracle_Mock is KeydonixOracleAbstract { - uint public rate = 1234; + /// @notice The current rate used to convert assets to USD. + uint public rate; + /* @notice Sets the rate used in the conversion from asset to USD. + * @param _rate The new rate to be set. + */ function setRate(uint _rate) public { rate = _rate; } + /* @notice Converts the amount of the asset to its equivalent in USD. + * @param amount The amount of the asset to convert. + * @param proofData The proof data required for the conversion, used here for validation. + * @return The equivalent amount in USD. + * @dev This mock implementation requires specific proofData to simulate the oracle check. + * @dev Throws if the proofData does not match the expected mock values. + */ function assetToUsd(address /* asset */, uint amount, ProofDataStruct memory proofData) public override view returns (uint) { require(keccak256(proofData.block) == keccak256(hex"01"), "Unit Protocol: proofData.block"); require(keccak256(proofData.accountProofNodesRlp) == keccak256(hex"02"), "Unit Protocol: proofData.accountProofNodesRlp"); @@ -28,4 +38,4 @@ contract KeydonixSimpleOracle_Mock is KeydonixOracleAbstract { return amount * rate; } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/OraclePoolToken_Mock.sol b/contracts/test-helpers/OraclePoolToken_Mock.sol index 9f2b780..3cf2ae2 100644 --- a/contracts/test-helpers/OraclePoolToken_Mock.sol +++ b/contracts/test-helpers/OraclePoolToken_Mock.sol @@ -12,31 +12,36 @@ import "../interfaces/IOracleUsd.sol"; import "../interfaces/IOracleRegistry.sol"; import "../interfaces/IToken.sol"; -/** - * @title OraclePoolToken_Mock - * @dev as OraclePoolToken but without flashloan resistance for test purposes - **/ +/* @title Mock Oracle for Uniswap LP tokens to test USD price determination + * @dev Extends IOracleUsd to provide USD price of Uniswap LP tokens for testing purposes + */ contract OraclePoolToken_Mock is IOracleUsd { using SafeMath for uint; + /* @notice Reference to the Oracle Registry contract */ IOracleRegistry public immutable oracleRegistry; + /* @notice Address of the Wrapped Ether (WETH) contract */ address public immutable WETH; + /* @notice Constant used for Q112 encoding (2**112) */ uint public immutable Q112 = 2 ** 112; + /* @notice Constructor to set the Oracle Registry and WETH addresses + * @param _oracleRegistry The address of the Oracle Registry contract + */ constructor(address _oracleRegistry) { oracleRegistry = IOracleRegistry(_oracleRegistry); WETH = IOracleRegistry(_oracleRegistry).WETH(); } - /** - * @notice Flashloan-resistant logic to determine USD price of Uniswap LP tokens - * @notice Pair must be registered at Chainlink - * @param asset The LP token address - * @param amount Amount of asset - * @return Q112 encoded price of asset in USD - **/ + /* @notice Returns the USD price of an asset + * @dev Calculates the price using Uniswap LP tokens and registered oracles + * @param asset The address of the LP token + * @param amount The amount of the LP token + * @return The price of the asset in USD, encoded in Q112 format + * @dev Throws if the pair is not registered or if the oracle is not found + */ function assetToUsd( address asset, uint amount @@ -95,4 +100,4 @@ contract OraclePoolToken_Mock is IOracleUsd { return IOracleEth(oracleRegistry.oracleByAsset(WETH)).ethToUsd(priceInEth); } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/SimpleOracle_Mock.sol b/contracts/test-helpers/SimpleOracle_Mock.sol index 11f646e..35befab 100644 --- a/contracts/test-helpers/SimpleOracle_Mock.sol +++ b/contracts/test-helpers/SimpleOracle_Mock.sol @@ -10,11 +10,17 @@ import "../interfaces/IOracleUsd.sol"; /** * @title SimpleOracle_Mock - * @dev Used in tests - **/ + * @dev Mock implementation of an oracle used for testing purposes. This mock oracle provides a simplistic conversion of an asset to its USD representation by multiplying the input amount by a fixed number. + */ contract SimpleOracle_Mock is IOracleUsd { + /** + * @notice Converts the asset amount to its equivalent USD value. + * @dev This mock function simply multiplies the input amount by a fixed conversion rate (1234). + * @param amount The amount of the asset to be converted to USD. + * @return uint The equivalent USD value of the input asset amount. + */ function assetToUsd(address /* asset */, uint amount) public override pure returns (uint) { return amount * 1234; } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/StETH.sol b/contracts/test-helpers/StETH.sol index 471a4f3..e312e7e 100644 --- a/contracts/test-helpers/StETH.sol +++ b/contracts/test-helpers/StETH.sol @@ -9,15 +9,27 @@ pragma solidity 0.7.6; import "./EmptyToken.sol"; import "../interfaces/IStETH.sol"; +/** + * @title StETH + * @dev Implementation of a staked ETH token. + */ contract StETH is IStETH, EmptyToken { using SafeMath for uint; + /// @notice Total amount of pooled Ether in the contract. uint256 public totalPooledEther; + + /// @dev Position of the total shares in contract storage. bytes32 internal constant TOTAL_SHARES_POSITION = keccak256("lido.StETH.totalShares"); + /** + * @notice Constructs the stETH token contract. + * @param _totalPooledEther Initial amount of pooled Ether. + * @param _totalShares Initial amount of shares. + */ constructor( - uint256 _totalPooledEther, - uint256 _totalShares + uint256 _totalPooledEther, + uint256 _totalShares ) EmptyToken( "Liquid staked Ether 2.0", "stETH", @@ -29,27 +41,55 @@ contract StETH is IStETH, EmptyToken { _mintShares(_totalShares); } + /** + * @dev Internal function to set a uint256 into contract storage. + * @param position Storage position to write to. + * @param data The uint256 data to write into storage. + */ function setStorageUint256(bytes32 position, uint256 data) internal { assembly { sstore(position, data) } } + /** + * @dev Internal function to mint shares. + * @param _sharesAmount The amount of shares to mint. + * @return newTotalShares The new total shares after minting. + */ function _mintShares(uint256 _sharesAmount) internal returns (uint256 newTotalShares) { newTotalShares = _getTotalShares().add(_sharesAmount); setStorageUint256(TOTAL_SHARES_POSITION, newTotalShares); } + /** + * @dev Internal view function to get a uint256 from contract storage. + * @param position Storage position to read from. + * @return data The uint256 data read from storage. + */ function getStorageUint256(bytes32 position) internal view returns (uint256 data) { assembly { data := sload(position) } } + /** + * @dev Internal view function to get the total shares. + * @return The total shares stored in the contract. + */ function _getTotalShares() internal view returns (uint256) { return getStorageUint256(TOTAL_SHARES_POSITION); } + /** + * @dev Internal view function to get the total pooled Ether. + * @return The total pooled Ether stored in the contract. + */ function _getTotalPooledEther() internal view returns (uint256) { return totalPooledEther; } + /** + * @notice Calculates the amount of pooled Ether corresponding to the given shares. + * @param _sharesAmount The amount of shares. + * @return The amount of pooled Ether that corresponds to the given shares. + */ function getPooledEthByShares(uint256 _sharesAmount) public override view returns (uint256) { uint256 totalShares = _getTotalShares(); if (totalShares == 0) { @@ -61,4 +101,4 @@ contract StETH is IStETH, EmptyToken { } } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/StETHCurvePool.sol b/contracts/test-helpers/StETHCurvePool.sol index 45a8c8b..29d2253 100644 --- a/contracts/test-helpers/StETHCurvePool.sol +++ b/contracts/test-helpers/StETHCurvePool.sol @@ -8,20 +8,40 @@ pragma solidity 0.7.6; import "../interfaces/IStableSwap.sol"; +/** + * @title StETHCurvePool + * @dev Implementation of a mock Curve pool for stETH/ETH trading pair. + */ contract StETHCurvePool is IStableSwap { + /// @notice The price of stETH in terms of ETH. uint256 public price; + /// @dev Index of stETH in the Curve pool. uint256 public constant CURVE_STETH_INDEX = 0; + /// @dev Index of ETH in the Curve pool. uint256 public constant CURVE_ETH_INDEX = 1; + /** + * @dev Sets the initial price of stETH. + * @param _price Initial price of stETH in terms of ETH. + */ constructor(uint256 _price) { price = _price; } + /** + * @notice Calculates the number of destination tokens you receive for the amount of source tokens you provide. + * @dev Mock implementation always returns the current price for a fixed input. + * @param x The index of the source token in the pool. + * @param y The index of the destination token in the pool. + * @param dx The amount of source tokens you want to convert. + * @return The amount of destination tokens you will receive. + * @throws if the input variables do not meet the required conditions. + */ function get_dy(uint256 x, uint256 y, uint256 dx) public override view returns (uint256) { require(x == CURVE_STETH_INDEX && y == CURVE_ETH_INDEX && dx == 10**18,'CHECK_INCOME_VARIABLES_FAILED'); return price; } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/StETHPriceFeed.sol b/contracts/test-helpers/StETHPriceFeed.sol index ce2766a..d418ba3 100644 --- a/contracts/test-helpers/StETHPriceFeed.sol +++ b/contracts/test-helpers/StETHPriceFeed.sol @@ -9,16 +9,32 @@ pragma solidity ^0.7.6; import "../interfaces/IStableSwap.sol"; import "../interfaces/IStableSwapStateOracle.sol"; +/** + * @title StETHPriceFeed + * @dev Contract to interact with the Curve pool for stETH and provide price feeds. + */ contract StETHPriceFeed { + /* @notice The address of the Curve pool contract. */ address public curve_pool_address; + + /* @notice The address of the stable swap state oracle contract. */ address public stable_swap_oracle_address; + + /* @notice Index of stETH in the Curve pool. */ uint256 public constant CURVE_STETH_INDEX = 0; + + /* @notice Index of ETH in the Curve pool. */ uint256 public constant CURVE_ETH_INDEX = 1; - // Maximal difference accepted is 10% (1000) + /* @notice Maximum accepted price difference in basis points. */ uint256 public constant max_safe_price_difference = 1000; + /** + * @dev Constructor for StETHPriceFeed. + * @param _curve_pool_address The address of the Curve pool. + * @param _stable_swap_oracle_address The address of the stable swap state oracle. + */ constructor( address _curve_pool_address, address _stable_swap_oracle_address @@ -27,6 +43,12 @@ contract StETHPriceFeed { stable_swap_oracle_address = _stable_swap_oracle_address; } + /** + * @dev Internal function to calculate the percentage difference between two values. + * @param newVal The new value for comparison. + * @param oldVal The old value for comparison. + * @return The percentage difference. + */ function _percentage_diff(uint256 newVal, uint256 oldVal) internal pure returns (uint256) { if (newVal > oldVal) { return (newVal - oldVal) * 10000 / oldVal; @@ -35,12 +57,23 @@ contract StETHPriceFeed { } } + /** + * @dev Internal function to fetch the current price from the Curve pool and compare it with the oracle price. + * @return pool_price The price from the Curve pool. + * @return has_changed_unsafely Boolean indicating if the price has changed unsafely. + * @return oracle_price The price from the oracle. + */ function _current_price() internal view returns (uint256 pool_price, bool has_changed_unsafely, uint256 oracle_price) { pool_price = IStableSwap(curve_pool_address).get_dy(CURVE_STETH_INDEX, CURVE_ETH_INDEX, 10**18); oracle_price = IStableSwapStateOracle(stable_swap_oracle_address).stethPrice(); has_changed_unsafely = _percentage_diff(pool_price, oracle_price) > max_safe_price_difference; } + /** + * @notice Fetches the current price and indicates if it's considered safe. + * @return The current price from the Curve pool. + * @return Boolean indicating if the price is considered safe. + */ function current_price() public view returns (uint256, bool) { uint256 currentPrice = 0; bool has_changed_unsafely = true; @@ -50,6 +83,12 @@ contract StETHPriceFeed { return (currentPrice, is_safe); } + /** + * @notice Fetches the full price information including the oracle price and safety status. + * @return The current price from the Curve pool. + * @return Boolean indicating if the price is considered safe. + * @return The current price from the oracle. + */ function full_price_info() public view returns (uint256, bool, uint256) { uint256 currentPrice = 0; bool has_changed_unsafely = true; @@ -59,4 +98,4 @@ contract StETHPriceFeed { return (currentPrice, is_safe, oracle_price); } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/StETHStableSwapOracle.sol b/contracts/test-helpers/StETHStableSwapOracle.sol index bc05622..6e6e20e 100644 --- a/contracts/test-helpers/StETHStableSwapOracle.sol +++ b/contracts/test-helpers/StETHStableSwapOracle.sol @@ -8,16 +8,31 @@ pragma solidity 0.7.6; import "../interfaces/IStableSwapStateOracle.sol"; +/* + * @title StETHStableSwapOracle + * @notice Oracle contract for stETH price that implements IStableSwapStateOracle interface. + * @dev This contract provides the functionality to report and retrieve the price of stETH. + */ contract StETHStableSwapOracle is IStableSwapStateOracle { + /* @notice The reported price of stETH */ uint256 public price; + /* + * @dev Constructor for StETHStableSwapOracle sets the initial price of stETH. + * @param _price The initial price of stETH to be set. + */ constructor(uint256 _price) { price = _price; } + /* + * @notice Gets the current price of stETH. + * @dev Returns the latest price of stETH reported by the oracle. + * @return The current price of stETH. + */ function stethPrice() public override view returns (uint256) { return price; } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/SwapperMock.sol b/contracts/test-helpers/SwapperMock.sol index f4020f0..37deba8 100644 --- a/contracts/test-helpers/SwapperMock.sol +++ b/contracts/test-helpers/SwapperMock.sol @@ -9,31 +9,61 @@ import "../interfaces/swappers/ISwapper.sol"; import "./IAssetTestsMint.sol"; import "../helpers/TransferHelper.sol"; -/** +/* * @title SwapperMock - * @dev Used in tests - **/ + * @dev Mock implementation of the ISwapper interface for testing purposes. + */ contract SwapperMock is ISwapper { + /* @notice The conversion rate from asset to USDP. */ uint public assetToUsdpRate = 1; + + /* @notice Address of the USDP token. */ address public immutable USDP; + /* + * @dev Sets the address of the USDP token upon contract creation. + * @param _usdp The address of the USDP token. + */ constructor(address _usdp) { USDP = _usdp; } + /* + * @dev Sets the conversion rate from asset to USDP for testing purposes. + * @param _rate The new conversion rate. + */ function tests_setAssetToUsdpRate(uint _rate) public { assetToUsdpRate = _rate; } + /* + * @dev Predicts the amount of asset that can be obtained for a given USDP amount. + * @param _usdpAmountIn The amount of USDP to be swapped. + * @return predictedAssetAmount The predicted amount of asset that will be received. + */ function predictAssetOut(address /* _asset */, uint256 _usdpAmountIn) external view override returns (uint predictedAssetAmount) { return _usdpAmountIn / assetToUsdpRate; } + /* + * @dev Predicts the amount of USDP that can be obtained for a given asset amount. + * @param _assetAmountIn The amount of asset to be swapped. + * @return predictedUsdpAmount The predicted amount of USDP that will be received. + */ function predictUsdpOut(address /* _asset */, uint256 _assetAmountIn) external view override returns (uint predictedUsdpAmount) { return _assetAmountIn * assetToUsdpRate; } + /* + * @dev Swaps USDP for asset and sends the asset to the specified user. + * @param _user The address of the user to receive the asset. + * @param _asset The address of the asset to be swapped. + * @param _usdpAmount The amount of USDP to be swapped. + * @param _minAssetAmount The minimum amount of asset expected to be received. + * @return swappedAssetAmount The amount of asset actually swapped. + * @notice The function requires the minimum asset amount to be equal to the result of the USDP amount divided by the conversion rate. + */ function swapUsdpToAsset(address _user, address _asset, uint256 _usdpAmount, uint256 _minAssetAmount) external override returns (uint swappedAssetAmount) { require(_minAssetAmount == _usdpAmount / assetToUsdpRate); // in _minAssetAmount we must send result of prediction. In tests the same TransferHelper.safeTransferFrom(USDP, _user, address(this), _usdpAmount); @@ -41,6 +71,15 @@ contract SwapperMock is ISwapper { return _minAssetAmount; } + /* + * @dev Swaps asset for USDP and sends the USDP to the specified user. + * @param _user The address of the user to receive the USDP. + * @param _asset The address of the asset to be swapped. + * @param _assetAmount The amount of asset to be swapped. + * @param _minUsdpAmount The minimum amount of USDP expected to be received. + * @return swappedUsdpAmount The amount of USDP actually swapped. + * @notice The function requires the minimum USDP amount to be equal to the result of the asset amount multiplied by the conversion rate. + */ function swapAssetToUsdp(address _user, address _asset, uint256 _assetAmount, uint256 _minUsdpAmount) external override returns (uint swappedUsdpAmount) { require(_minUsdpAmount == _assetAmount * assetToUsdpRate); // in _minAssetAmount we must send result of prediction. In tests the same TransferHelper.safeTransferFrom(_asset, _user, address(this), _assetAmount); @@ -48,15 +87,32 @@ contract SwapperMock is ISwapper { return _minUsdpAmount; } + /* + * @dev Swaps USDP for asset and directly sends the asset to the specified user without transferring USDP to the contract first. + * @param _user The address of the user to receive the asset. + * @param _asset The address of the asset to be swapped. + * @param _usdpAmount The amount of USDP to be swapped. + * @param _minAssetAmount The minimum amount of asset expected to be received. + * @return swappedAssetAmount The amount of asset actually swapped. + * @notice The function requires the minimum asset amount to be equal to the result of the USDP amount divided by the conversion rate. + */ function swapUsdpToAssetWithDirectSending(address _user, address _asset, uint256 _usdpAmount, uint256 _minAssetAmount) external override returns (uint swappedAssetAmount) { require(_minAssetAmount == _usdpAmount / assetToUsdpRate); // in _minAssetAmount we must send result of prediction. In tests the same IAssetTestsMint(_asset).tests_mint(_user, _minAssetAmount); return _minAssetAmount; } + /* + * @dev Swaps asset for USDP and directly sends the USDP to the specified user without transferring the asset to the contract first. + * @param _user The address of the user to receive the USDP. + * @param _assetAmount The amount of asset to be swapped. + * @param _minUsdpAmount The minimum amount of USDP expected to be received. + * @return swappedUsdpAmount The amount of USDP actually swapped. + * @notice The function requires the minimum USDP amount to be equal to the result of the asset amount multiplied by the conversion rate. + */ function swapAssetToUsdpWithDirectSending(address _user, address /* _asset */, uint256 _assetAmount, uint256 _minUsdpAmount) external override returns (uint swappedUsdpAmount) { require(_minUsdpAmount == _assetAmount * assetToUsdpRate); // in _minAssetAmount we must send result of prediction. In tests the same IAssetTestsMint(USDP).tests_mint(_user, _minUsdpAmount); return _minUsdpAmount; } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/USDPMock.sol b/contracts/test-helpers/USDPMock.sol index 9eeedb2..dd5775b 100644 --- a/contracts/test-helpers/USDPMock.sol +++ b/contracts/test-helpers/USDPMock.sol @@ -8,16 +8,31 @@ pragma solidity 0.7.6; import "../USDP.sol"; import "./IAssetTestsMint.sol"; - +/** + * @title USDPMock + * @dev Mock contract for USDP token used for testing purposes. + * Inherits from USDP and implements the IAssetTestsMint interface. + */ contract USDPMock is USDP, IAssetTestsMint { - using SafeMath for uint; + using SafeMath for uint; - constructor(address _parameters) USDP(_parameters) {} + /** + * @dev Constructor that initializes the USDPMock contract. + * @param _parameters The address of the contract containing system parameters. + */ + constructor(address _parameters) USDP(_parameters) {} - function tests_mint(address to, uint amount) public override { - require(to != address(0), "Unit Protocol: ZERO_ADDRESS"); + /** + * @dev Mints USDP tokens to a specified address for testing purposes. + * @param to The address to which the tokens will be minted. + * @param amount The amount of tokens to mint. + * Requirements: + * - `to` cannot be the zero address. + */ + function tests_mint(address to, uint amount) public override { + require(to != address(0), "Unit Protocol: ZERO_ADDRESS"); - balanceOf[to] = balanceOf[to].add(amount); - totalSupply = totalSupply.add(amount); - } -} + balanceOf[to] = balanceOf[to].add(amount); + totalSupply = totalSupply.add(amount); + } +} \ No newline at end of file diff --git a/contracts/test-helpers/UniswapV2Library.sol b/contracts/test-helpers/UniswapV2Library.sol index a882460..8b2cdc2 100644 --- a/contracts/test-helpers/UniswapV2Library.sol +++ b/contracts/test-helpers/UniswapV2Library.sol @@ -8,17 +8,33 @@ pragma solidity 0.7.6; import "../helpers/SafeMath.sol"; import "../helpers/IUniswapV2PairFull.sol"; +/** + * @title UniswapV2Library + * @dev Provides functions for interacting with UniswapV2 pairs. + */ library UniswapV2Library { using SafeMath for uint; - // returns sorted token addresses, used to handle return values from pairs sorted in this order + /** + * @dev Sorts and returns token addresses in ascending order to avoid duplicates. + * @param tokenA The address of the first token. + * @param tokenB The address of the second token. + * @return token0 The address of the lower token. + * @return token1 The address of the higher token. + */ function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES'); (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS'); } - // calculates the CREATE2 address for a pair without making any external calls + /** + * @dev Calculates the CREATE2 address for a pair without making any external calls. + * @param factory The address of the Uniswap factory contract. + * @param tokenA The address of the first token. + * @param tokenB The address of the second token. + * @return pair The address of the Uniswap pair. + */ function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) { (address token0, address token1) = sortTokens(tokenA, tokenB); pair = address(uint(keccak256(abi.encodePacked( @@ -29,21 +45,40 @@ library UniswapV2Library { )))); } - // fetches and sorts the reserves for a pair + /** + * @dev Fetches and sorts the reserves for a pair. + * @param factory The address of the Uniswap factory contract. + * @param tokenA The address of the first token. + * @param tokenB The address of the second token. + * @return reserveA The reserve of tokenA. + * @return reserveB The reserve of tokenB. + */ function getReserves(address factory, address tokenA, address tokenB) internal view returns (uint reserveA, uint reserveB) { (address token0,) = sortTokens(tokenA, tokenB); (uint reserve0, uint reserve1,) = IUniswapV2PairFull(pairFor(factory, tokenA, tokenB)).getReserves(); (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0); } - // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset + /** + * @dev Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset. + * @param amountA The amount of tokenA. + * @param reserveA The reserve of tokenA. + * @param reserveB The reserve of tokenB. + * @return amountB The equivalent amount of tokenB. + */ function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) { require(amountA > 0, 'UniswapV2Library: INSUFFICIENT_AMOUNT'); require(reserveA > 0 && reserveB > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); amountB = amountA.mul(reserveB) / reserveA; } - // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset + /** + * @dev Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset. + * @param amountIn The input amount of the asset. + * @param reserveIn The reserve of the input asset. + * @param reserveOut The reserve of the output asset. + * @return amountOut The maximum output amount. + */ function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) { require(amountIn > 0, 'UniswapV2Library: INSUFFICIENT_INPUT_AMOUNT'); require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); @@ -53,7 +88,13 @@ library UniswapV2Library { amountOut = numerator / denominator; } - // given an output amount of an asset and pair reserves, returns a required input amount of the other asset + /** + * @dev Given an output amount of an asset and pair reserves, returns a required input amount of the other asset. + * @param amountOut The output amount of the asset. + * @param reserveIn The reserve of the input asset. + * @param reserveOut The reserve of the output asset. + * @return amountIn The required input amount. + */ function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) { require(amountOut > 0, 'UniswapV2Library: INSUFFICIENT_OUTPUT_AMOUNT'); require(reserveIn > 0 && reserveOut > 0, 'UniswapV2Library: INSUFFICIENT_LIQUIDITY'); @@ -62,7 +103,13 @@ library UniswapV2Library { amountIn = (numerator / denominator).add(1); } - // performs chained getAmountOut calculations on any number of pairs + /** + * @dev Performs chained getAmountOut calculations on any number of pairs. + * @param factory The address of the Uniswap factory contract. + * @param amountIn The input amount of the asset. + * @param path An array of token addresses. + * @return amounts The output amounts of each token in the path. + */ function getAmountsOut(address factory, uint amountIn, address[] memory path) internal view returns (uint[] memory amounts) { require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); amounts = new uint[](path.length); @@ -73,7 +120,13 @@ library UniswapV2Library { } } - // performs chained getAmountIn calculations on any number of pairs + /** + * @dev Performs chained getAmountIn calculations on any number of pairs. + * @param factory The address of the Uniswap factory contract. + * @param amountOut The output amount of the asset. + * @param path An array of token addresses. + * @return amounts The input amounts of each token in the path. + */ function getAmountsIn(address factory, uint amountOut, address[] memory path) internal view returns (uint[] memory amounts) { require(path.length >= 2, 'UniswapV2Library: INVALID_PATH'); amounts = new uint[](path.length); @@ -83,4 +136,4 @@ library UniswapV2Library { amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut); } } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/UniswapV2Router02.sol b/contracts/test-helpers/UniswapV2Router02.sol index f6249af..6527b43 100644 --- a/contracts/test-helpers/UniswapV2Router02.sol +++ b/contracts/test-helpers/UniswapV2Router02.sol @@ -13,27 +13,53 @@ import '../helpers/TransferHelper.sol'; import './UniswapV2Library.sol'; import '../interfaces/IWETH.sol'; +/* + * @title UniswapV2Router02 + * @dev Implementation of the Uniswap V2 Router, facilitating liquidity addition and removal, and token swaps. + */ contract UniswapV2Router02 { using SafeMath for uint; address public immutable factory; address payable public immutable weth; + /* + * @dev Modifier to ensure the transaction is executed before the deadline. + * @param deadline Unix timestamp after which the transaction will revert. + */ modifier ensure(uint deadline) { require(deadline >= block.timestamp, 'UniswapV2Router: EXPIRED'); _; } + /* + * @notice Constructs the UniswapV2Router02 contract. + * @param _factory The address of the Uniswap V2 factory contract. + * @param _WETH The address of the Wrapped Ether (WETH) contract. + */ constructor(address _factory, address payable _WETH) { factory = _factory; weth = _WETH; } + /* + * @dev Allows the router to receive ETH. + */ receive() external payable { assert(msg.sender == weth); // only accept ETH via fallback from the WETH contract } - // **** ADD LIQUIDITY **** + /* + * @dev Internal function to add liquidity. + * @param tokenA The address of the first token. + * @param tokenB The address of the second token. + * @param amountADesired Desired amount of token A to add as liquidity. + * @param amountBDesired Desired amount of token B to add as liquidity. + * @param amountAMin Minimum amount of token A to add as liquidity. + * @param amountBMin Minimum amount of token B to add as liquidity. + * @return amountA The actual amount of token A added as liquidity. + * @return amountB The actual amount of token B added as liquidity. + */ function _addLiquidity( address tokenA, address tokenB, @@ -62,6 +88,21 @@ contract UniswapV2Router02 { } } } + + /* + * @notice Adds liquidity for a token pair. + * @param tokenA The address of the first token. + * @param tokenB The address of the second token. + * @param amountADesired Desired amount of token A to add as liquidity. + * @param amountBDesired Desired amount of token B to add as liquidity. + * @param amountAMin Minimum amount of token A to add as liquidity. + * @param amountBMin Minimum amount of token B to add as liquidity. + * @param to The address that will receive the liquidity tokens. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amountA The actual amount of token A added as liquidity. + * @return amountB The actual amount of token B added as liquidity. + * @return liquidity The amount of liquidity tokens minted. + */ function addLiquidity( address tokenA, address tokenB, @@ -78,6 +119,19 @@ contract UniswapV2Router02 { TransferHelper.safeTransferFrom(tokenB, msg.sender, pair, amountB); liquidity = IUniswapV2PairFull(pair).mint(to); } + + /* + * @notice Adds liquidity for a token and ETH pair. + * @param token The address of the token. + * @param amountTokenDesired Desired amount of token to add as liquidity. + * @param amountTokenMin Minimum amount of token to add as liquidity. + * @param amountETHMin Minimum amount of ETH to add as liquidity. + * @param to The address that will receive the liquidity tokens. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amountToken The actual amount of token added as liquidity. + * @return amountETH The actual amount of ETH added as liquidity. + * @return liquidity The amount of liquidity tokens minted. + */ function addLiquidityETH( address token, uint amountTokenDesired, @@ -104,6 +158,19 @@ contract UniswapV2Router02 { } // **** REMOVE LIQUIDITY **** + + /* + * @notice Removes liquidity from a token pair and returns the underlying tokens to the caller. + * @param tokenA The address of the first token in the liquidity pair. + * @param tokenB The address of the second token in the liquidity pair. + * @param liquidity The amount of liquidity tokens to remove. + * @param amountAMin The minimum amount of token A that must be received for the transaction not to revert. + * @param amountBMin The minimum amount of token B that must be received for the transaction not to revert. + * @param to The address to which the withdrawn tokens should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amountA The amount of token A received. + * @return amountB The amount of token B received. + */ function removeLiquidity( address tokenA, address tokenB, @@ -121,6 +188,18 @@ contract UniswapV2Router02 { require(amountA >= amountAMin, 'UniswapV2Router: INSUFFICIENT_A_AMOUNT'); require(amountB >= amountBMin, 'UniswapV2Router: INSUFFICIENT_B_AMOUNT'); } + + /* + * @notice Removes liquidity from a ETH/token pair and returns the underlying tokens and ETH to the caller. + * @param token The address of the ERC-20 token in the liquidity pair. + * @param liquidity The amount of liquidity tokens to remove. + * @param amountTokenMin The minimum amount of token that must be received for the transaction not to revert. + * @param amountETHMin The minimum amount of ETH that must be received for the transaction not to revert. + * @param to The address to which the withdrawn tokens and ETH should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amountToken The amount of token received. + * @return amountETH The amount of ETH received. + */ function removeLiquidityETH( address token, uint liquidity, @@ -142,6 +221,23 @@ contract UniswapV2Router02 { IWETH(weth).withdraw(amountETH); TransferHelper.safeTransferETH(to, amountETH); } + + /* + * @notice Allows a user to remove liquidity with a permit, bypassing the approval step. + * @param tokenA The address of the first token in the liquidity pair. + * @param tokenB The address of the second token in the liquidity pair. + * @param liquidity The amount of liquidity tokens to remove. + * @param amountAMin The minimum amount of token A that must be received for the transaction not to revert. + * @param amountBMin The minimum amount of token B that must be received for the transaction not to revert. + * @param to The address to which the withdrawn tokens should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @param approveMax Boolean indicating whether to approve the maximum amount or exact liquidity amount. + * @param v Component of the signature. + * @param r Component of the signature. + * @param s Component of the signature. + * @return amountA The amount of token A received. + * @return amountB The amount of token B received. + */ function removeLiquidityWithPermit( address tokenA, address tokenB, @@ -157,6 +253,22 @@ contract UniswapV2Router02 { IUniswapV2PairFull(pair).permit(msg.sender, address(this), value, deadline, v, r, s); (amountA, amountB) = removeLiquidity(tokenA, tokenB, liquidity, amountAMin, amountBMin, to, deadline); } + + /* + * @notice Similar to `removeLiquidity`, but for ETH/token pairs and allows the use of a permit. + * @param token The address of the ERC-20 token in the liquidity pair. + * @param liquidity The amount of liquidity tokens to remove. + * @param amountTokenMin The minimum amount of token that must be received for the transaction not to revert. + * @param amountETHMin The minimum amount of ETH that must be received for the transaction not to revert. + * @param to The address to which the withdrawn tokens and ETH should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @param approveMax Boolean indicating whether to approve the maximum amount or exact liquidity amount. + * @param v Component of the signature. + * @param r Component of the signature. + * @param s Component of the signature. + * @return amountToken The amount of token received. + * @return amountETH The amount of ETH received. + */ function removeLiquidityETHWithPermit( address token, uint liquidity, @@ -173,6 +285,22 @@ contract UniswapV2Router02 { } // **** REMOVE LIQUIDITY (supporting fee-on-transfer tokens) **** + + /* + * @notice Similar to `removeLiquidity`, but for ETH/token pairs and allows the use of a permit. + * @param token The address of the ERC-20 token in the liquidity pair. + * @param liquidity The amount of liquidity tokens to remove. + * @param amountTokenMin The minimum amount of token that must be received for the transaction not to revert. + * @param amountETHMin The minimum amount of ETH that must be received for the transaction not to revert. + * @param to The address to which the withdrawn tokens and ETH should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @param approveMax Boolean indicating whether to approve the maximum amount or exact liquidity amount. + * @param v Component of the signature. + * @param r Component of the signature. + * @param s Component of the signature. + * @return amountToken The amount of token received. + * @return amountETH The amount of ETH received. + */ function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, @@ -194,6 +322,21 @@ contract UniswapV2Router02 { IWETH(weth).withdraw(amountETH); TransferHelper.safeTransferETH(to, amountETH); } + + /* + * @notice Allows the removal of liquidity with a permit for a token pair that supports fee-on-transfer. + * @param token The address of the ERC-20 token in the liquidity pair that supports fee-on-transfer. + * @param liquidity The amount of liquidity tokens to remove. + * @param amountTokenMin The minimum amount of token that must be received for the transaction not to revert. + * @param amountETHMin The minimum amount of ETH that must be received for the transaction not to revert. + * @param to The address to which the withdrawn tokens and ETH should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @param approveMax Boolean indicating whether to approve the maximum amount or exact liquidity amount. + * @param v Component of the signature. + * @param r Component of the signature. + * @param s Component of the signature. + * @return amountETH The amount of ETH received after removing liquidity. + */ function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, @@ -213,6 +356,20 @@ contract UniswapV2Router02 { // **** SWAP **** // requires the initial amount to have already been sent to the first pair + /* + * @notice Allows the removal of liquidity with a permit for a token pair that supports fee-on-transfer. + * @param token The address of the ERC-20 token in the liquidity pair that supports fee-on-transfer. + * @param liquidity The amount of liquidity tokens to remove. + * @param amountTokenMin The minimum amount of token that must be received for the transaction not to revert. + * @param amountETHMin The minimum amount of ETH that must be received for the transaction not to revert. + * @param to The address to which the withdrawn tokens and ETH should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @param approveMax Boolean indicating whether to approve the maximum amount or exact liquidity amount. + * @param v Component of the signature. + * @param r Component of the signature. + * @param s Component of the signature. + * @return amountETH The amount of ETH received after removing liquidity. + */ function _swap(uint[] memory amounts, address[] memory path, address _to) internal virtual { for (uint i; i < path.length - 1; i++) { (address input, address output) = (path[i], path[i + 1]); @@ -225,6 +382,16 @@ contract UniswapV2Router02 { ); } } + + /* + * @notice Swaps an exact amount of input tokens for as many output tokens as possible, adhering to the specified minimum output amount. + * @param amountIn The amount of input tokens to send. + * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert. + * @param path An array of token addresses. This array will encode the path of the swap. + * @param to The address to which the output tokens should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amounts The amounts of each token involved in the swaps. + */ function swapExactTokensForTokens( uint amountIn, uint amountOutMin, @@ -239,6 +406,16 @@ contract UniswapV2Router02 { ); _swap(amounts, path, to); } + + /* + * @notice Swaps tokens for as few input tokens as possible, exactly meeting the desired output amount. + * @param amountOut The amount of output tokens to receive. + * @param amountInMax The maximum amount of input tokens that can be sent. + * @param path An array of token addresses. This array will encode the path of the swap. + * @param to The address to which the output tokens should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amounts The amounts of each token involved in the swaps. + */ function swapTokensForExactTokens( uint amountOut, uint amountInMax, @@ -253,6 +430,15 @@ contract UniswapV2Router02 { ); _swap(amounts, path, to); } + + /* + * @notice Swaps an exact amount of ETH for as many output tokens as possible, adhering to the specified minimum output amount. + * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert. + * @param path An array of token addresses. This array will encode the path of the swap. The first element must be WETH. + * @param to The address to which the output tokens should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amounts The amounts of each token involved in the swaps. + */ function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external virtual @@ -267,6 +453,16 @@ contract UniswapV2Router02 { assert(IWETH(weth).transfer(UniswapV2Library.pairFor(factory, path[0], path[1]), amounts[0])); _swap(amounts, path, to); } + + /* + * @notice Swaps tokens for as much ETH as possible, adhering to the specified minimum amount of ETH. + * @param amountOut The amount of ETH to receive. + * @param amountInMax The maximum amount of input tokens that can be sent. + * @param path An array of token addresses. This array will encode the path of the swap. The last element must be WETH. + * @param to The address to which the ETH should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amounts The amounts of each token involved in the swaps. + */ function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external virtual @@ -283,6 +479,16 @@ contract UniswapV2Router02 { IWETH(weth).withdraw(amounts[amounts.length - 1]); TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]); } + + /* + * @notice Swaps an exact amount of input tokens for ETH. + * @param amountIn The amount of input tokens to send. + * @param amountOutMin The minimum amount of ETH that must be received for the transaction not to revert. + * @param path An array of token addresses. This array will encode the path of the swap. The last element must be WETH. + * @param to The address to which the ETH should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amounts The amounts of each token involved in the swaps. + */ function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external virtual @@ -299,6 +505,15 @@ contract UniswapV2Router02 { IWETH(weth).withdraw(amounts[amounts.length - 1]); TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]); } + + /* + * @notice Swaps as much ETH as possible to exactly meet the desired amount of output tokens. + * @param amountOut The amount of output tokens to receive. + * @param path An array of token addresses. This array will encode the path of the swap. The first element must be WETH. + * @param to The address to which the output tokens should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + * @return amounts The amounts of each token involved in the swaps. + */ function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external virtual @@ -318,6 +533,13 @@ contract UniswapV2Router02 { // **** SWAP (supporting fee-on-transfer tokens) **** // requires the initial amount to have already been sent to the first pair + + /* + * @notice Internal function to execute a swap for a given path, supporting tokens with a fee-on-transfer mechanism. + * @param path An array of token addresses representing the path of the swap. + * @param _to The address to which the output tokens should be sent. + * @dev This function assumes that the initial amount of the input token has already been sent to the first pair. + */ function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to) internal virtual { for (uint i; i < path.length - 1; i++) { (address input, address output) = (path[i], path[i + 1]); @@ -336,6 +558,15 @@ contract UniswapV2Router02 { pair.swap(amount0Out, amount1Out, to, new bytes(0)); } } + + /* + * @notice Swaps an exact amount of input tokens for as many output tokens as possible, adhering to the specified minimum output amount and supporting fee-on-transfer tokens. + * @param amountIn The amount of input tokens to send. + * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert. + * @param path An array of token addresses, encoding the path of the swap. Fee-on-transfer tokens can be included in the path. + * @param to The address to which the output tokens should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + */ function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, @@ -353,6 +584,14 @@ contract UniswapV2Router02 { 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT' ); } + + /* + * @notice Swaps an exact amount of ETH for as many output tokens as possible, adhering to the specified minimum output amount and supporting fee-on-transfer tokens. + * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert. + * @param path An array of token addresses, encoding the path of the swap. Fee-on-transfer tokens can be included in the path. The first element must be WETH. + * @param to The address to which the output tokens should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + */ function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, @@ -376,6 +615,14 @@ contract UniswapV2Router02 { ); } + /* + * @notice Swaps an exact amount of input tokens for ETH, adhering to the specified minimum amount of ETH and supporting fee-on-transfer tokens. + * @param amountIn The amount of input tokens to send. + * @param amountOutMin The minimum amount of ETH that must be received for the transaction not to revert. + * @param path An array of token addresses, encoding the path of the swap. Fee-on-transfer tokens can be included in the path. The last element must be WETH. + * @param to The address to which the ETH should be sent. + * @param deadline Unix timestamp after which the transaction will revert. + */ function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, @@ -399,10 +646,25 @@ contract UniswapV2Router02 { } // **** LIBRARY FUNCTIONS **** + + /* + * @notice Provides an estimate for the amount of one token required to purchase a given amount of another token. + * @param amountA The amount of the first token. + * @param reserveA The reserve of the first token in the liquidity pool. + * @param reserveB The reserve of the second token in the liquidity pool. + * @return amountB The estimated amount of the second token that can be purchased with the given amount of the first token. + */ function quote(uint amountA, uint reserveA, uint reserveB) public pure virtual returns (uint amountB) { return UniswapV2Library.quote(amountA, reserveA, reserveB); } + /* + * @notice Calculates the amount of output tokens one would receive given an input amount and the reserves of a pair. + * @param amountIn The amount of input tokens. + * @param reserveIn The reserve of the input token in the liquidity pool. + * @param reserveOut The reserve of the output token in the liquidity pool. + * @return amountOut The calculated amount of output tokens. + */ function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) public pure @@ -412,6 +674,13 @@ contract UniswapV2Router02 { return UniswapV2Library.getAmountOut(amountIn, reserveIn, reserveOut); } + /* + * @notice Calculates the amount of input tokens one would need to provide to receive a specified amount of output tokens. + * @param amountOut The desired amount of output tokens. + * @param reserveIn The reserve of the input token in the liquidity pool. + * @param reserveOut The reserve of the output token in the liquidity pool. + * @return amountIn The calculated amount of input tokens required. + */ function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) public pure @@ -421,6 +690,12 @@ contract UniswapV2Router02 { return UniswapV2Library.getAmountIn(amountOut, reserveIn, reserveOut); } + /* + * @notice Returns the amounts of each token in the path that the user would receive if they sent a specified amount of the first token in the path. + * @param amountIn The amount of the first token in the path to send. + * @param path An array of token addresses which form the path of the swap. + * @return amounts The amounts of each token in the path that would be received. + */ function getAmountsOut(uint amountIn, address[] memory path) public view @@ -430,6 +705,12 @@ contract UniswapV2Router02 { return UniswapV2Library.getAmountsOut(factory, amountIn, path); } + /* + * @notice Returns the amounts of each token in the path that a user would need to send to receive a specified amount of the last token in the path. + * @param amountOut The desired amount of the last token in the path. + * @param path An array of token addresses which form the path of the swap. + * @return amounts The amounts of each token in the path that would need to be sent. + */ function getAmountsIn(uint amountOut, address[] memory path) public view diff --git a/contracts/test-helpers/WETHMock.sol b/contracts/test-helpers/WETHMock.sol index 322ab58..5d301c7 100644 --- a/contracts/test-helpers/WETHMock.sol +++ b/contracts/test-helpers/WETHMock.sol @@ -9,6 +9,7 @@ import "./IAssetTestsMint.sol"; import "../interfaces/IWETH.sol"; import "../helpers/SafeMath.sol"; +/* @title Mock contract for Wrapped Ether (WETH) */ contract WETHMock is IWETH, IAssetTestsMint { using SafeMath for uint; @@ -16,23 +17,33 @@ contract WETHMock is IWETH, IAssetTestsMint { string public symbol = "WETH"; uint8 public decimals = 18; - event Approval(address indexed src, address indexed guy, uint wad); - event Transfer(address indexed src, address indexed dst, uint wad); - event Deposit(address indexed dst, uint wad); - event Withdrawal(address indexed src, uint wad); + event Approval(address indexed src, address indexed guy, uint wad); + event Transfer(address indexed src, address indexed dst, uint wad); + event Deposit(address indexed dst, uint wad); + event Withdrawal(address indexed src, uint wad); mapping (address => uint) public balanceOf; mapping (address => mapping (address => uint)) public allowance; uint testsMinted = 0; + /* @dev Allows contract to receive Ether */ receive() external payable { deposit(); } + + /* + * @dev Deposits Ether to wrap into WETH + */ function deposit() public override payable { balanceOf[msg.sender] += msg.value; emit Deposit(msg.sender, msg.value); } + + /* + * @dev Withdraws Ether by unwrapping WETH + * @param wad The amount of WETH to unwrap + */ function withdraw(uint wad) public override { require(balanceOf[msg.sender] >= wad); balanceOf[msg.sender] -= wad; @@ -40,20 +51,43 @@ contract WETHMock is IWETH, IAssetTestsMint { emit Withdrawal(msg.sender, wad); } + /* + * @dev Returns the total supply of WETH, including any test minted amount + * @return The total supply of WETH + */ function totalSupply() public view returns (uint) { return address(this).balance + testsMinted; } + /* + * @dev Approves another address to spend WETH on the caller's behalf + * @param guy The address to approve + * @param wad The amount of WETH to approve + * @return A boolean value indicating whether the operation succeeded + */ function approve(address guy, uint wad) public returns (bool) { allowance[msg.sender][guy] = wad; Approval(msg.sender, guy, wad); return true; } + /* + * @dev Transfers WETH to another address + * @param dst The destination address + * @param wad The amount of WETH to transfer + * @return A boolean value indicating whether the operation succeeded + */ function transfer(address dst, uint wad) public override returns (bool) { return transferFrom(msg.sender, dst, wad); } + /* + * @dev Transfers WETH from one address to another + * @param src The source address + * @param dst The destination address + * @param wad The amount of WETH to transfer + * @return A boolean value indicating whether the operation succeeded + */ function transferFrom(address src, address dst, uint wad) public override returns (bool) @@ -73,10 +107,15 @@ contract WETHMock is IWETH, IAssetTestsMint { return true; } + /* + * @dev Mints WETH for testing purposes + * @param to The address to mint WETH to + * @param amount The amount of WETH to mint + */ function tests_mint(address to, uint amount) public override { require(to != address(0), "Unit Protocol: ZERO_ADDRESS"); balanceOf[to] = balanceOf[to].add(amount); testsMinted = testsMinted.add(amount); } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/WrappedAssetMock.sol b/contracts/test-helpers/WrappedAssetMock.sol index 42a8a0e..cf982a8 100644 --- a/contracts/test-helpers/WrappedAssetMock.sol +++ b/contracts/test-helpers/WrappedAssetMock.sol @@ -7,33 +7,49 @@ pragma solidity 0.7.6; import "../helpers/TransferHelper.sol"; import "../interfaces/wrapped-assets/IWrappedAsset.sol"; - import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; /** - * @title SwapperMock - * @dev Used in tests - **/ + * @title WrappedAssetMock + * @dev Mock contract for wrapped assets, used for testing purposes. + */ contract WrappedAssetMock is ERC20, IWrappedAsset { + /// @notice Address of the underlying token. address public underlyingToken; + + /// @dev Unique identifier for Unit Protocol wrapped assets. bytes32 public constant override isUnitProtocolWrappedAsset = keccak256("UnitProtocolWrappedAsset"); + /** + * @dev Initializes the contract by setting a `name` and a `symbol` to the token. + * @param _underlyingToken Address of the underlying token. + */ constructor(address _underlyingToken) ERC20('TestsWA', 'Tests wrapped asset') { underlyingToken = _underlyingToken; } + /** + * @notice Returns the address of the underlying token. + * @return IERC20 The IERC20 interface of the underlying token. + */ function getUnderlyingToken() external view override returns (IERC20) { return IERC20(underlyingToken); } + /** + * @notice Sets a new underlying token address. + * @param _underlyingToken The address of the new underlying token. + */ function setUnderlyingToken(address _underlyingToken) external { underlyingToken = _underlyingToken; } /** - * @notice deposit underlying token and send wrapped token to user - * @dev Important! Only user or trusted contracts must be able to call this method + * @notice Deposits the underlying token and mints the wrapped token to the user. + * @dev This function should only be callable by the user or trusted contracts. + * @param _userAddr The address of the user to receive the wrapped tokens. + * @param _amount The amount of the underlying token to deposit. */ function deposit(address _userAddr, uint256 _amount) external override { // no caller check since it is for tests only @@ -42,8 +58,10 @@ contract WrappedAssetMock is ERC20, IWrappedAsset { } /** - * @notice get wrapped token and return underlying - * @dev Important! Only user or trusted contracts must be able to call this method + * @notice Withdraws the underlying token by burning the wrapped token. + * @dev This function should only be callable by the user or trusted contracts. + * @param _userAddr The address of the user to return the underlying tokens to. + * @param _amount The amount of the wrapped token to burn. */ function withdraw(address _userAddr, uint256 _amount) external override { // no caller check since it is for tests only @@ -52,20 +70,28 @@ contract WrappedAssetMock is ERC20, IWrappedAsset { } /** - * @notice get pending reward amount for user if reward is supported + * @notice Returns the pending reward amount for the user, if rewards are supported. + * @dev This function always returns 0, as rewards are not implemented in this mock. + * @param /** _userAddr */ The address of the user to check the pending rewards for. + * @return uint256 The pending reward amount, which is always 0. */ function pendingReward(address /** _userAddr */) external pure override returns (uint256) { return 0; } /** - * @notice claim pending reward for user if reward is supported + * @notice Claims the pending rewards for the user, if rewards are supported. + * @dev This function is a no-op, as rewards are not implemented in this mock. + * @param /** _userAddr */ The address of the user to claim rewards for. */ function claimReward(address /** _userAddr */) external override {} /** - * @notice Manually move position (or its part) to another user (for example in case of liquidation) - * @dev Important! Only trusted contracts must be able to call this method + * @notice Moves a position, or part of it, to another user, for example in case of liquidation. + * @dev This function should only be callable by trusted contracts. + * @param /** _userAddrFrom */ The address of the user from whom the position is moved. + * @param /** _userAddrTo */ The address of the user to whom the position is moved. + * @param /** _amount */ The amount of the position to move. */ function movePosition(address /** _userAddrFrom */, address /** _userAddrTo */, uint256 /** _amount */) external override {} -} +} \ No newline at end of file diff --git a/contracts/test-helpers/WstETH.sol b/contracts/test-helpers/WstETH.sol index 9844938..6d871e8 100644 --- a/contracts/test-helpers/WstETH.sol +++ b/contracts/test-helpers/WstETH.sol @@ -10,13 +10,25 @@ import "./EmptyToken.sol"; import "../interfaces/IWstEthToken.sol"; import "../interfaces/IStETH.sol"; +/** + * @title WstETH + * @dev This contract wraps stETH tokens into wstETH tokens to provide liquidity. + */ contract WstETH is EmptyToken, IWstEthToken { + /** + * @dev Address of the stETH token. + */ address public stETHAddr; + /** + * @notice Creates an instance of the wstETH token. + * @param _totalSupply Initial total supply of wstETH. + * @param _stEth Address of the stETH token to wrap. + */ constructor( - uint256 _totalSupply, - address _stEth + uint256 _totalSupply, + address _stEth ) EmptyToken( "Wrapped liquid staked Ether 2.0", "wstETH", @@ -27,12 +39,21 @@ contract WstETH is EmptyToken, IWstEthToken { stETHAddr = _stEth; } + /** + * @notice Given an amount of wstETH, calculates the amount of stETH that the wstETH is worth. + * @param _wstETHAmount Amount of wstETH to convert to stETH. + * @return The equivalent amount of stETH. + */ function getStETHByWstETH(uint256 _wstETHAmount) public override view returns (uint256) { return IStETH(stETHAddr).getPooledEthByShares(_wstETHAmount); } + /** + * @notice Gets the current address of the stETH token. + * @return The address of the stETH token. + */ function stETH() public override view returns (address) { return stETHAddr; } -} +} \ No newline at end of file diff --git a/contracts/test-helpers/YvWETH.sol b/contracts/test-helpers/YvWETH.sol index 5030e4f..04513e3 100644 --- a/contracts/test-helpers/YvWETH.sol +++ b/contracts/test-helpers/YvWETH.sol @@ -7,27 +7,38 @@ pragma solidity 0.7.6; import "./EmptyToken.sol"; - +/* + * @title YvWETH + * @notice YvWETH is a contract for a token that represents a share of a pool of WETH in the Yearn Finance protocol. + * @dev Inheritance from EmptyToken contract with added functionality specific to a yVault for WETH. + */ contract YvWETH is EmptyToken { + /* @notice Address of the underlying token which is WETH. */ address public token; + /* @notice The price per share of the yVault, denominated in the underlying token. */ uint256 public pricePerShare; - - constructor( - uint256 _totalSupply, - address _token, - uint256 _pricePerShare - ) EmptyToken( - "WETH yVault", - "yvWETH", - 18, - _totalSupply, - msg.sender - ) { - token = _token; - pricePerShare = _pricePerShare; - } - -} + /* + * @dev Constructor for YvWETH which sets up the yVault token. + * @param _totalSupply The initial total supply of yVault tokens. + * @param _token The address of the underlying token, which should be WETH. + * @param _pricePerShare The initial price per share for the yVault. + */ + constructor( + uint256 _totalSupply, + address _token, + uint256 _pricePerShare + ) EmptyToken( + "WETH yVault", + "yvWETH", + 18, + _totalSupply, + msg.sender + ) { + token = _token; + pricePerShare = _pricePerShare; + } + +} \ No newline at end of file diff --git a/contracts/vault-managers/BaseCDPManager.sol b/contracts/vault-managers/BaseCDPManager.sol index 83f81e1..722c68b 100644 --- a/contracts/vault-managers/BaseCDPManager.sol +++ b/contracts/vault-managers/BaseCDPManager.sol @@ -23,8 +23,9 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @title BaseCDPManager - * @dev all common logic should be moved here in future - **/ + * @notice Abstract contract for Collateralized Debt Position (CDP) management in Unit Protocol. + * @dev Contains common logic for CDP management, with future scope for extension. + */ abstract contract BaseCDPManager is ReentrancyGuard { using SafeMath for uint; @@ -71,12 +72,13 @@ abstract contract BaseCDPManager is ReentrancyGuard { } /** + * @notice Constructs the BaseCDPManager contract. * @param _vaultManagerParameters The address of the contract with Vault manager parameters * @param _vaultManagerBorrowFeeParameters The address of the vault manager borrow fee parameters * @param _oracleRegistry The address of the oracle registry * @param _cdpRegistry The address of the CDP registry * @param _swappersRegistry The address of the swappers registry - **/ + */ constructor( address _vaultManagerParameters, address _vaultManagerBorrowFeeParameters, @@ -104,7 +106,12 @@ abstract contract BaseCDPManager is ReentrancyGuard { } /** - * @notice Charge borrow fee if needed + * @notice Charges a borrow fee if needed when borrowing USDP against collateral. + * @param asset The address of the collateral asset. + * @param user The address of the user borrowing USDP. + * @param usdpAmount The amount of USDP being borrowed. + * @return borrowFee The calculated borrow fee. + * @dev Throws an error if the USDP allowance for the fee is not approved by the user. */ function _chargeBorrowFee(address asset, address user, uint usdpAmount) internal returns (uint borrowFee) { borrowFee = vaultManagerBorrowFeeParameters.calcBorrowFeeAmount(asset, usdpAmount); @@ -123,7 +130,13 @@ abstract contract BaseCDPManager is ReentrancyGuard { ); } - // decreases debt + /** + * @notice Repays a portion of the debt in USDP. + * @param asset The address of the collateral asset. + * @param owner The owner of the debt. + * @param usdpAmount The amount of USDP to repay. + * @dev Destroys the CDP if the debt after repayment is zero. + */ function _repay(address asset, address owner, uint usdpAmount) internal { uint fee = vault.calculateFee(asset, owner, usdpAmount); vault.chargeFee(vault.usdp(), owner, fee); @@ -137,11 +150,11 @@ abstract contract BaseCDPManager is ReentrancyGuard { } /** - * @dev Calculates liquidation price - * @param asset The address of the collateral - * @param owner The owner of the position - * @return Q112-encoded liquidation price - **/ + * @notice Calculates the liquidation price for a given collateral and owner. + * @param asset The address of the collateral. + * @param owner The owner of the position. + * @return The liquidation price, Q112-encoded. + */ function liquidationPrice_q112( address asset, address owner @@ -157,7 +170,11 @@ abstract contract BaseCDPManager is ReentrancyGuard { } /** - * @dev Returned asset amount + charged stability fee on this amount = repayment (in fact <= repayment bcs of rounding error) + * @notice Calculates the principal amount for a given repayment. + * @param asset The address of the collateral asset. + * @param owner The owner of the debt. + * @param repayment The total repayment amount. + * @return The principal amount of the repayment. */ function _calcPrincipal(address asset, address owner, uint repayment) internal view returns (uint) { uint multiplier = repayment; @@ -176,12 +193,12 @@ abstract contract BaseCDPManager is ReentrancyGuard { } /** - * @dev Determines whether a position is liquidatable - * @param asset The address of the collateral - * @param owner The owner of the position - * @param usdValue_q112 Q112-encoded USD value of the collateral - * @return boolean value, whether a position is liquidatable - **/ + * @notice Determines whether a position is liquidatable. + * @param asset The address of the collateral. + * @param owner The owner of the position. + * @param usdValue_q112 Q112-encoded USD value of the collateral. + * @return A boolean indicating whether the position is liquidatable. + */ function _isLiquidatablePosition( address asset, address owner, @@ -195,6 +212,12 @@ abstract contract BaseCDPManager is ReentrancyGuard { return debt.mul(100).mul(Q112).div(usdValue_q112) >= vaultManagerParameters.liquidationRatio(asset); } + /** + * @notice Ensures the existence of an oracle for a given asset. + * @param asset The address of the asset. + * @return oracleType The type of the oracle. + * @dev Throws an error if the oracle type is invalid or the oracle is disabled. + */ function _ensureOracle(address asset) internal view virtual returns (uint oracleType) { oracleType = oracleRegistry.oracleTypeByAsset(asset); require(oracleType != 0, "Unit Protocol: INVALID_ORACLE_TYPE"); @@ -203,6 +226,13 @@ abstract contract BaseCDPManager is ReentrancyGuard { require(oracle != address(0), "Unit Protocol: DISABLED_ORACLE"); } + /** + * @notice Mints USDP against the provided collateral. + * @param _asset The address of the collateral asset. + * @param _owner The owner of the collateral. + * @param _amount The amount of USDP to mint. + * @return usdpAmountToUser The net amount of USDP provided to the user after fees. + */ function _mintUsdp(address _asset, address _owner, uint _amount) internal returns (uint usdpAmountToUser) { uint oracleType = _ensureOracle(_asset); @@ -219,6 +249,16 @@ abstract contract BaseCDPManager is ReentrancyGuard { return _amount.sub(borrowFee); } + /** + * @notice Swaps USDP to a specified asset and performs checks on the swapped amount. + * @param swapper The ISwapper interface to perform the swap. + * @param _asset The address of the asset to swap to. + * @param _usdpAmountToSwap The amount of USDP to swap. + * @param _minSwappedAssetAmount The minimum acceptable amount of the asset to receive from the swap. + * @return swappedAssetAmount The actual amount of the asset received from the swap. + * @dev Verifies that the swapped amount is at least the minimum specified and the balance changes are as expected. + * Throws an error if the swapped amount is less than the minimum or if the balance changes are not as expected. + */ function _swapUsdpToAssetAndCheck(ISwapper swapper, address _asset, uint _usdpAmountToSwap, uint _minSwappedAssetAmount) internal returns(uint swappedAssetAmount) { uint assetBalanceBeforeSwap = IERC20(_asset).balanceOf(msg.sender); uint usdpBalanceBeforeSwap = usdp.balanceOf(msg.sender); @@ -230,6 +270,16 @@ abstract contract BaseCDPManager is ReentrancyGuard { require(usdp.balanceOf(msg.sender) == usdpBalanceBeforeSwap.sub(_usdpAmountToSwap), "Unit Protocol: INVALID_USDP_AMOUNT_GOT_FOR_SWAP_BY_SWAPPER"); } + /** + * @notice Swaps a specified asset to USDP and performs checks on the swapped amount. + * @param swapper The ISwapper interface to perform the swap. + * @param _asset The address of the asset to swap. + * @param _assetAmountToSwap The amount of the asset to swap. + * @param _minSwappedUsdpAmount The minimum acceptable amount of USDP to receive from the swap. + * @return swappedUsdpAmount The actual amount of USDP received from the swap. + * @dev Verifies that the swapped amount is at least the minimum specified and the balance changes are as expected. + * Throws an error if the swapped amount is less than the minimum or if the balance changes are not as expected. + */ function _swapAssetToUsdpAndCheck(ISwapper swapper, address _asset, uint _assetAmountToSwap, uint _minSwappedUsdpAmount) internal returns(uint swappedUsdpAmount) { uint assetBalanceBeforeSwap = IERC20(_asset).balanceOf(msg.sender); uint usdpBalanceBeforeSwap = usdp.balanceOf(msg.sender); diff --git a/contracts/vault-managers/CDPManager_Fallback.sol b/contracts/vault-managers/CDPManager_Fallback.sol index 521df7b..2c14644 100644 --- a/contracts/vault-managers/CDPManager_Fallback.sol +++ b/contracts/vault-managers/CDPManager_Fallback.sol @@ -22,7 +22,10 @@ import '../helpers/SafeMath.sol'; /** * @title CDPManager01_Fallback - **/ + * @dev This contract allows users to manage their Collateralized Debt Positions (CDPs). + * Users can deposit collateral tokens, borrow stablecoins against them, and repay the debt. + * This contract includes functionality for leveraged positions and handling wrapped tokens. + */ contract CDPManager01_Fallback is BaseCDPManager { using SafeMath for uint; diff --git a/contracts/vault-managers/parameters/AssetParameters.sol b/contracts/vault-managers/parameters/AssetParameters.sol index fd3b545..952dcb4 100644 --- a/contracts/vault-managers/parameters/AssetParameters.sol +++ b/contracts/vault-managers/parameters/AssetParameters.sol @@ -5,28 +5,37 @@ */ pragma solidity 0.7.6; -/** +/* * @title AssetParameters - **/ + * @dev Library to handle asset-specific parameters for liquidation logic. + */ library AssetParameters { - /** - * Some assets require a transfer of at least 1 unit of token - * to update internal logic related to staking rewards in case of full liquidation + /* Some assets require a transfer of at least 1 unit of token + * to update internal logic related to staking rewards in case of full liquidation. */ uint8 public constant PARAM_FORCE_TRANSFER_ASSET_TO_OWNER_ON_LIQUIDATION = 0; - /** - * Some wrapped assets that require a manual position transfer between users - * since `transfer` doesn't do this + /* Some wrapped assets that require a manual position transfer between users + * since `transfer` doesn't do this. */ uint8 public constant PARAM_FORCE_MOVE_WRAPPED_ASSET_POSITION_ON_LIQUIDATION = 1; + /** + * @dev Determines if an asset requires force transfer to owner on liquidation. + * @param assetBoolParams The encoded boolean parameters for the asset. + * @return bool True if force transfer is needed, false otherwise. + */ function needForceTransferAssetToOwnerOnLiquidation(uint256 assetBoolParams) internal pure returns (bool) { return assetBoolParams & (1 << PARAM_FORCE_TRANSFER_ASSET_TO_OWNER_ON_LIQUIDATION) != 0; } + /** + * @dev Determines if a wrapped asset requires a manual position transfer on liquidation. + * @param assetBoolParams The encoded boolean parameters for the wrapped asset. + * @return bool True if manual position transfer is needed, false otherwise. + */ function needForceMoveWrappedAssetPositionOnLiquidation(uint256 assetBoolParams) internal pure returns (bool) { return assetBoolParams & (1 << PARAM_FORCE_MOVE_WRAPPED_ASSET_POSITION_ON_LIQUIDATION) != 0; } -} +} \ No newline at end of file diff --git a/contracts/vault-managers/parameters/AssetsBooleanParameters.sol b/contracts/vault-managers/parameters/AssetsBooleanParameters.sol index 8d2d772..d112aea 100644 --- a/contracts/vault-managers/parameters/AssetsBooleanParameters.sol +++ b/contracts/vault-managers/parameters/AssetsBooleanParameters.sol @@ -8,14 +8,19 @@ pragma solidity 0.7.6; import "../../Auth2.sol"; import "../../interfaces/vault-managers/parameters/IAssetsBooleanParameters.sol"; - -/** - * @title AssetsBooleanParameters - **/ +/* @title Manages boolean parameters for assets in the Unit Protocol system. */ contract AssetsBooleanParameters is Auth2, IAssetsBooleanParameters { mapping(address => uint256) internal values; + /* + @notice Constructor to initialize the contract with initial assets and their parameters. + @param _vaultParameters The address of the VaultParameters contract. + @param _initialAssets Array of asset addresses to initialize. + @param _initialParams Array of initial parameter values for each asset. + @dev _initialAssets and _initialParams must be the same length. + @dev Throws if the length of _initialAssets and _initialParams does not match. + */ constructor(address _vaultParameters, address[] memory _initialAssets, uint8[] memory _initialParams) Auth2(_vaultParameters) { require(_initialAssets.length == _initialParams.length, "Unit Protocol: ARGUMENTS_LENGTH_MISMATCH"); @@ -24,29 +29,45 @@ contract AssetsBooleanParameters is Auth2, IAssetsBooleanParameters { } } - /** - * @notice Get value of _param for _asset - * @dev see ParametersConstants - **/ + /* + @notice Retrieves the boolean value of a specified parameter for an asset. + @param _asset The address of the asset. + @param _param The parameter index to retrieve. + @return The boolean value of the specified parameter for the given asset. + */ function get(address _asset, uint8 _param) external override view returns (bool) { return values[_asset] & (1 << _param) != 0; } - /** - * @notice Get values of all params for _asset. The 0th bit of returned uint id the value of param=0, etc - **/ + /* + @notice Retrieves all parameter values for an asset as a single uint256. + @param _asset The address of the asset. + @return A uint256 representing all parameter values for the given asset. + */ function getAll(address _asset) external override view returns (uint256) { return values[_asset]; } - /** - * @notice Set value of _param for _asset - * @dev see ParametersConstants - **/ + /* + @notice Sets the boolean value of a specified parameter for an asset. + @param _asset The address of the asset. + @param _param The parameter index to set. + @param _value The boolean value to set for the specified parameter. + @dev Emits a ValueSet or ValueUnset event upon success. + @dev Only callable by the manager role. + */ function set(address _asset, uint8 _param, bool _value) public override onlyManager { _set(_asset, _param, _value); } + /* + @notice Internal function to set the boolean value of a specified parameter for an asset. + @param _asset The address of the asset. + @param _param The parameter index to set. + @param _value The boolean value to set for the specified parameter. + @dev Emits a ValueSet or ValueUnset event upon success. + @dev Throws if trying to set a value for the zero address. + */ function _set(address _asset, uint8 _param, bool _value) internal { require(_asset != address(0), "Unit Protocol: ZERO_ADDRESS"); @@ -58,4 +79,4 @@ contract AssetsBooleanParameters is Auth2, IAssetsBooleanParameters { emit ValueUnset(_asset, _param, values[_asset]); } } -} +} \ No newline at end of file diff --git a/contracts/vault-managers/parameters/VaultManagerBorrowFeeParameters.sol b/contracts/vault-managers/parameters/VaultManagerBorrowFeeParameters.sol index 0700b6a..7688f62 100644 --- a/contracts/vault-managers/parameters/VaultManagerBorrowFeeParameters.sol +++ b/contracts/vault-managers/parameters/VaultManagerBorrowFeeParameters.sol @@ -9,39 +9,55 @@ import "../../VaultParameters.sol"; import "../../interfaces/vault-managers/parameters/IVaultManagerBorrowFeeParameters.sol"; import "../../helpers/SafeMath.sol"; - /** * @title VaultManagerBorrowFeeParameters - **/ + * @dev Contract for managing the borrow fee parameters in the Unit Protocol system. + */ contract VaultManagerBorrowFeeParameters is Auth, IVaultManagerBorrowFeeParameters { using SafeMath for uint; + // Basis points in one, for fee calculations. uint public constant override BASIS_POINTS_IN_1 = 1e4; + // Struct to hold asset-specific borrow fee parameters. struct AssetBorrowFeeParams { - bool enabled; // is custom fee for asset enabled - uint16 feeBasisPoints; // fee basis points, 1 basis point = 0.0001 + bool enabled; // Whether the custom fee for asset is enabled. + uint16 feeBasisPoints; // Fee in basis points, where 1 basis point = 0.0001. } - // map token to borrow fee + // Mapping from token addresses to their respective borrow fee parameters. mapping(address => AssetBorrowFeeParams) public assetBorrowFee; + + // The base borrow fee in basis points for all assets, unless overridden. uint16 public baseBorrowFeeBasisPoints; + // Address where the collected fees are sent. address public override feeReceiver; + // Event emitted when asset-specific borrow fee parameters are enabled. event AssetBorrowFeeParamsEnabled(address asset, uint16 feeBasisPoints); + + // Event emitted when asset-specific borrow fee parameters are disabled. event AssetBorrowFeeParamsDisabled(address asset); + // Modifier to ensure the address is not zero. modifier nonZeroAddress(address addr) { require(addr != address(0), "Unit Protocol: ZERO_ADDRESS"); _; } + // Modifier to ensure the fee is within correct range. modifier correctFee(uint16 fee) { require(fee < BASIS_POINTS_IN_1, "Unit Protocol: INCORRECT_FEE_VALUE"); _; } + /** + * @dev Constructor for VaultManagerBorrowFeeParameters. + * @param _vaultParameters Address of the VaultParameters contract. + * @param _baseBorrowFeeBasisPoints The initial base borrow fee in basis points. + * @param _feeReceiver Address where the collected fees are sent. + */ constructor(address _vaultParameters, uint16 _baseBorrowFeeBasisPoints, address _feeReceiver) Auth(_vaultParameters) nonZeroAddress(_feeReceiver) @@ -51,17 +67,31 @@ contract VaultManagerBorrowFeeParameters is Auth, IVaultManagerBorrowFeeParamete feeReceiver = _feeReceiver; } - /// @inheritdoc IVaultManagerBorrowFeeParameters + /** + * @notice Sets the fee receiver address. + * @dev Can only be called by the manager role. + * @param newFeeReceiver The address of the new fee receiver. + */ function setFeeReceiver(address newFeeReceiver) external override onlyManager nonZeroAddress(newFeeReceiver) { feeReceiver = newFeeReceiver; } - /// @inheritdoc IVaultManagerBorrowFeeParameters + /** + * @notice Sets the base borrow fee in basis points. + * @dev Can only be called by the manager role. + * @param newBaseBorrowFeeBasisPoints The new base borrow fee in basis points. + */ function setBaseBorrowFee(uint16 newBaseBorrowFeeBasisPoints) external override onlyManager correctFee(newBaseBorrowFeeBasisPoints) { baseBorrowFeeBasisPoints = newBaseBorrowFeeBasisPoints; } - /// @inheritdoc IVaultManagerBorrowFeeParameters + /** + * @notice Sets the asset-specific borrow fee parameters. + * @dev Can only be called by the manager role. + * @param asset The address of the asset token. + * @param newEnabled Whether the custom fee for the asset is enabled. + * @param newFeeBasisPoints The fee in basis points for the asset. + */ function setAssetBorrowFee(address asset, bool newEnabled, uint16 newFeeBasisPoints) external override onlyManager correctFee(newFeeBasisPoints) { assetBorrowFee[asset].enabled = newEnabled; assetBorrowFee[asset].feeBasisPoints = newFeeBasisPoints; @@ -73,7 +103,11 @@ contract VaultManagerBorrowFeeParameters is Auth, IVaultManagerBorrowFeeParamete } } - /// @inheritdoc IVaultManagerBorrowFeeParameters + /** + * @notice Retrieves the borrow fee in basis points for a given asset. + * @param asset The address of the asset token. + * @return feeBasisPoints The fee in basis points for the asset. + */ function getBorrowFee(address asset) public override view returns (uint16 feeBasisPoints) { if (assetBorrowFee[asset].enabled) { return assetBorrowFee[asset].feeBasisPoints; @@ -82,7 +116,12 @@ contract VaultManagerBorrowFeeParameters is Auth, IVaultManagerBorrowFeeParamete return baseBorrowFeeBasisPoints; } - /// @inheritdoc IVaultManagerBorrowFeeParameters + /** + * @notice Calculates the borrow fee amount for a given asset and USDP amount. + * @param asset The address of the asset token. + * @param usdpAmount The amount of USDP for which to calculate the fee. + * @return The calculated borrow fee amount. + */ function calcBorrowFeeAmount(address asset, uint usdpAmount) external override view returns (uint) { uint16 borrowFeeBasisPoints = getBorrowFee(asset); if (borrowFeeBasisPoints == 0) { @@ -91,4 +130,4 @@ contract VaultManagerBorrowFeeParameters is Auth, IVaultManagerBorrowFeeParamete return usdpAmount.mul(uint(borrowFeeBasisPoints)).div(BASIS_POINTS_IN_1); } -} +} \ No newline at end of file diff --git a/contracts/vault-managers/parameters/VaultManagerParameters.sol b/contracts/vault-managers/parameters/VaultManagerParameters.sol index 66bba75..4a567f4 100644 --- a/contracts/vault-managers/parameters/VaultManagerParameters.sol +++ b/contracts/vault-managers/parameters/VaultManagerParameters.sol @@ -10,27 +10,32 @@ import "../../VaultParameters.sol"; /** * @title VaultManagerParameters - **/ + * @dev Contract to manage parameters for vaults in the Unit Protocol system. + */ contract VaultManagerParameters is Auth { - // determines the minimum percentage of COL token part in collateral, 0 decimals + /* @notice Minimum percentage of COL token part in collateral (0 decimals) */ mapping(address => uint) public minColPercent; - // determines the maximum percentage of COL token part in collateral, 0 decimals + /* @notice Maximum percentage of COL token part in collateral (0 decimals) */ mapping(address => uint) public maxColPercent; - // map token to initial collateralization ratio; 0 decimals + /* @notice Initial collateralization ratio for a given token (0 decimals) */ mapping(address => uint) public initialCollateralRatio; - // map token to liquidation ratio; 0 decimals + /* @notice Liquidation ratio for a given token (0 decimals) */ mapping(address => uint) public liquidationRatio; - // map token to liquidation discount; 3 decimals + /* @notice Liquidation discount for a given token (3 decimals) */ mapping(address => uint) public liquidationDiscount; - // map token to devaluation period in blocks + /* @notice Devaluation period in blocks for a given token */ mapping(address => uint) public devaluationPeriod; + /** + * @dev Initializes the contract by setting a `vaultParameters` address. + * @param _vaultParameters Address of the VaultParameters contract. + */ constructor(address _vaultParameters) Auth(_vaultParameters) {} /** @@ -125,4 +130,4 @@ contract VaultManagerParameters is Auth { minColPercent[asset] = min; maxColPercent[asset] = max; } -} +} \ No newline at end of file diff --git a/contracts/wrapped-assets/shiba/WSSLPUserProxy.sol b/contracts/wrapped-assets/shiba/WSSLPUserProxy.sol index a5b7fd8..9dcb192 100644 --- a/contracts/wrapped-assets/shiba/WSSLPUserProxy.sol +++ b/contracts/wrapped-assets/shiba/WSSLPUserProxy.sol @@ -13,21 +13,29 @@ import "../../helpers/TransferHelper.sol"; /** * @title WSSLPUserProxy - **/ + * @dev Proxy contract for managing Wrapped Sushiswap Liquidity Pool (WSSLP) interactions. + */ contract WSSLPUserProxy { using SafeMath for uint256; address public immutable manager; - ITopDog public immutable topDog; uint256 public immutable topDogPoolId; IERC20 public immutable boneToken; + /** + * @dev Ensures that only the manager can call the function. + */ modifier onlyManager() { require(msg.sender == manager, "Unit Protocol Wrapped Assets: AUTH_FAILED"); _; } + /** + * @dev Sets the manager to the creator of the contract, and initializes contract state. + * @param _topDog Address of the TopDog contract. + * @param _topDogPoolId Pool ID for the TopDog contract. + */ constructor(ITopDog _topDog, uint256 _topDogPoolId) { manager = msg.sender; @@ -38,21 +46,39 @@ contract WSSLPUserProxy { } /** - * @dev in case of change sslp + * @dev Approves the specified amount of SSLP tokens to be managed by the TopDog contract. + * This is necessary in case of a change in SSLP. + * @param _sslpToken Address of the SSLP token to be approved. */ function approveSslpToTopDog(IERC20 _sslpToken) public onlyManager { TransferHelper.safeApprove(address(_sslpToken), address(topDog), type(uint256).max); } + /** + * @dev Deposits the specified amount of SSLP tokens into the TopDog pool. + * @param _amount Amount of SSLP tokens to deposit. + */ function deposit(uint256 _amount) public onlyManager { topDog.deposit(topDogPoolId, _amount); } + /** + * @dev Withdraws the specified amount of SSLP tokens from the TopDog pool. + * @param _sslpToken Address of the SSLP token to withdraw. + * @param _amount Amount of SSLP tokens to withdraw. + * @param _sentTokensTo Address to send the withdrawn tokens to. + */ function withdraw(IERC20 _sslpToken, uint256 _amount, address _sentTokensTo) public onlyManager { topDog.withdraw(topDogPoolId, _amount); TransferHelper.safeTransfer(address(_sslpToken), _sentTokensTo, _amount); } + /** + * @dev Calculates the pending reward, accounting for fees. + * @param _feeReceiver Address to send the fee to. + * @param _feePercent Percentage of the reward that will be taken as a fee. + * @return amountWithoutFee Amount of reward after fee deduction. + */ function pendingReward(address _feeReceiver, uint8 _feePercent) public view returns (uint) { uint balance = boneToken.balanceOf(address(this)); uint pending = topDog.pendingBone(topDogPoolId, address(this)).mul(topDog.rewardMintPercent()).div(100); @@ -61,12 +87,26 @@ contract WSSLPUserProxy { return amountWithoutFee; } + /** + * @dev Claims the reward, accounting for fees, and sends it to the user. + * @param _user Address to send the reward to. + * @param _feeReceiver Address to send the fee to. + * @param _feePercent Percentage of the reward that will be taken as a fee. + */ function claimReward(address _user, address _feeReceiver, uint8 _feePercent) public onlyManager { topDog.deposit(topDogPoolId, 0); // get current reward (no separate methods) _sendAllBonesToUser(_user, _feeReceiver, _feePercent); } + /** + * @dev Internal function to calculate the fee and amount after fee deduction. + * @param _amount Amount to calculate the fee on. + * @param _feeReceiver Address to send the fee to. If this is address(0), no fee is applied. + * @param _feePercent Percentage of the amount that will be taken as a fee. + * @return amountWithoutFee Amount after fee deduction. + * @return fee Calculated fee amount. + */ function _calcFee(uint _amount, address _feeReceiver, uint8 _feePercent) internal pure returns (uint amountWithoutFee, uint fee) { if (_feePercent == 0 || _feeReceiver == address(0)) { return (_amount, 0); @@ -76,12 +116,25 @@ contract WSSLPUserProxy { return (_amount.sub(fee), fee); } + /** + * @dev Internal function for sending all BONE tokens to the specified user, accounting for fees. + * @param _user Address to send the BONE tokens to. + * @param _feeReceiver Address to send the fee to. + * @param _feePercent Percentage of the reward that will be taken as a fee. + */ function _sendAllBonesToUser(address _user, address _feeReceiver, uint8 _feePercent) internal { uint balance = boneToken.balanceOf(address(this)); _sendBonesToUser(_user, balance, _feeReceiver, _feePercent); } + /** + * @dev Internal function for sending specified amount of BONE tokens to the user, accounting for fees. + * @param _user Address to send the BONE tokens to. + * @param _amount Amount of BONE tokens to send. + * @param _feeReceiver Address to send the fee to. + * @param _feePercent Percentage of the amount that will be taken as a fee. + */ function _sendBonesToUser(address _user, uint _amount, address _feeReceiver, uint8 _feePercent) internal { (uint amountWithoutFee, uint fee) = _calcFee(_amount, _feeReceiver, _feePercent); @@ -91,6 +144,13 @@ contract WSSLPUserProxy { TransferHelper.safeTransfer(address(boneToken), _user, amountWithoutFee); } + /** + * @dev Calculates claimable reward from BoneLocker, accounting for fees. + * @param _boneLocker Address of the BoneLocker contract. + * @param _feeReceiver Address to send the fee to. + * @param _feePercent Percentage of the reward that will be taken as a fee. + * @return amountWithoutFee Amount of reward after fee deduction. + */ function getClaimableRewardFromBoneLocker(IBoneLocker _boneLocker, address _feeReceiver, uint8 _feePercent) public view returns (uint) { if (address(_boneLocker) == address(0)) { _boneLocker = topDog.boneLocker(); @@ -100,6 +160,14 @@ contract WSSLPUserProxy { return amountWithoutFee; } + /** + * @dev Claims rewards from the BoneLocker contract, subject to a maximum limit per claim, and accounts for fees. + * @param _user Address to send the claimed BONE tokens to. + * @param _boneLocker Address of the BoneLocker contract. + * @param _maxBoneLockerRewardsAtOneClaim Maximum amount of rewards that can be claimed in one transaction. + * @param _feeReceiver Address to send the fee to. + * @param _feePercent Percentage of the reward that will be taken as a fee. + */ function claimRewardFromBoneLocker(address _user, IBoneLocker _boneLocker, uint256 _maxBoneLockerRewardsAtOneClaim, address _feeReceiver, uint8 _feePercent) public onlyManager { if (address(_boneLocker) == address(0)) { _boneLocker = topDog.boneLocker(); @@ -118,10 +186,22 @@ contract WSSLPUserProxy { _sendAllBonesToUser(_user, _feeReceiver, _feePercent); } + + /** + * @dev Emergency function for withdrawing all deposits from the TopDog pool. + */ function emergencyWithdraw() public onlyManager { topDog.emergencyWithdraw(topDogPoolId); } + /** + * @dev Withdraws a specified token from the contract, accounting for fees. + * @param _token Address of the token to withdraw. + * @param _user Address to send the withdrawn tokens to. + * @param _amount Amount of tokens to withdraw. + * @param _feeReceiver Address to send the fee to. + * @param _feePercent Percentage of the withdrawal amount that will be taken as a fee. + */ function withdrawToken(address _token, address _user, uint _amount, address _feeReceiver, uint8 _feePercent) public onlyManager { if (_token == address(boneToken)) { _sendBonesToUser(_user, _amount, _feeReceiver, _feePercent); @@ -130,15 +210,33 @@ contract WSSLPUserProxy { } } + /** + * @dev Reads data from the BoneLocker contract without altering state. + * @param _boneLocker Address of the BoneLocker contract. + * @param _callData Calldata to be sent to the BoneLocker contract. + * @return success Boolean indicating if the call was successful. + * @return data Data returned from the BoneLocker contract. + */ function readBoneLocker(address _boneLocker, bytes calldata _callData) public view returns (bool success, bytes memory data) { (success, data) = _boneLocker.staticcall(_callData); } + /** + * @dev Calls a function on the BoneLocker contract. + * @param _boneLocker Address of the BoneLocker contract. + * @param _callData Calldata to be sent to the BoneLocker contract. + * @return success Boolean indicating if the call was successful. + * @return data Data returned from the BoneLocker contract. + */ function callBoneLocker(address _boneLocker, bytes calldata _callData) public onlyManager returns (bool success, bytes memory data) { (success, data) = _boneLocker.call(_callData); } + /** + * @dev Returns the amount of tokens deposited by this contract in the TopDog pool. + * @return amount Amount of tokens deposited in the TopDog pool. + */ function getDepositedAmount() public view returns (uint amount) { - (amount, ) = topDog.userInfo(topDogPoolId, address (this)); + (amount, ) = topDog.userInfo(topDogPoolId, address(this)); } } diff --git a/contracts/wrapped-assets/shiba/WrappedShibaSwapLp.sol b/contracts/wrapped-assets/shiba/WrappedShibaSwapLp.sol index 53e9c96..a42bf7b 100644 --- a/contracts/wrapped-assets/shiba/WrappedShibaSwapLp.sol +++ b/contracts/wrapped-assets/shiba/WrappedShibaSwapLp.sol @@ -20,25 +20,39 @@ import "../../interfaces/wrapped-assets/ISushiSwapLpToken.sol"; /** * @title ShibaSwapWrappedLp + * @dev Contract for wrapping ShibaSwap LP tokens. + * Inherits from IWrappedAsset, Auth2, ERC20, and ReentrancyGuard. **/ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { using SafeMath for uint256; + // Unique identifier for Unit Protocol Wrapped Asset bytes32 public constant override isUnitProtocolWrappedAsset = keccak256("UnitProtocolWrappedAsset"); + // References to external contracts and immutable variables IVault public immutable vault; ITopDog public immutable topDog; uint256 public immutable topDogPoolId; IERC20 public immutable boneToken; - address public immutable userProxyImplementation; + + // User proxy mapping mapping(address => WSSLPUserProxy) public usersProxies; + // Allowed selectors for bone lockers mapping (address => mapping (bytes4 => bool)) allowedBoneLockersSelectors; + // Fee management variables address public feeReceiver; uint8 public feePercent = 10; + /** + * @dev Constructor for WrappedShibaSwapLp. + * @param _vaultParameters Address of the vault parameters. + * @param _topDog Address of the TopDog contract. + * @param _topDogPoolId Pool ID for the TopDog contract. + * @param _feeReceiver Address where fees are sent. + */ constructor( address _vaultParameters, ITopDog _topDog, @@ -79,12 +93,26 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { userProxyImplementation = address(new WSSLPUserProxy(_topDog, _topDogPoolId)); } + + + /** + * @dev Sets the fee receiver address. + * @param _feeReceiver The address to which fees should be sent. + * @notice Only callable by the contract manager. + * @emit FeeReceiverChanged Emits the new fee receiver address. + */ function setFeeReceiver(address _feeReceiver) public onlyManager { feeReceiver = _feeReceiver; emit FeeReceiverChanged(_feeReceiver); } + /** + * @dev Sets the fee percentage. + * @param _feePercent The new fee percentage, cannot exceed 50%. + * @notice Only callable by the contract manager. + * @emit FeeChanged Emits the new fee percentage. + */ function setFee(uint8 _feePercent) public onlyManager { require(_feePercent <= 50, "Unit Protocol Wrapped Assets: INVALID_FEE"); feePercent = _feePercent; @@ -93,32 +121,38 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @dev in case of change bone locker to unsupported by current methods one + * @dev Allows or disallows a selector on a bone locker. + * @param _boneLocker Address of the bone locker. + * @param _selector The function selector to allow or disallow. + * @param _isAllowed Boolean value indicating whether the selector is allowed. + * @notice Only callable by the contract manager. */ function setAllowedBoneLockerSelector(address _boneLocker, bytes4 _selector, bool _isAllowed) public onlyManager { allowedBoneLockersSelectors[_boneLocker][_selector] = _isAllowed; - if (_isAllowed) { emit AllowedBoneLockerSelectorAdded(_boneLocker, _selector); } else { - emit AllowedBoneLockerSelectorRemoved(_boneLocker, _selector); + emit AllowedBoneLockerSelectorRemoved(_boneLocker, _selector); } } - /** - * @notice Approve sslp token to spend from user proxy (in case of change sslp) + * @dev Approves the SSLP token to be spent by the TopDog contract. + * @notice Should be called in case of SSLP token change. + * @notice Only callable by the user proxy. */ function approveSslpToTopDog() public nonReentrant { WSSLPUserProxy userProxy = _requireUserProxy(msg.sender); IERC20 sslpToken = getUnderlyingToken(); - userProxy.approveSslpToTopDog(sslpToken); } /** - * @notice Get tokens from user, send them to TopDog, sent to user wrapped tokens - * @dev only user or CDPManager could call this method + * @dev Allows deposit of SSLP tokens and issues wrapped tokens to the user. + * @param _user Address of the user making the deposit. + * @param _amount Amount of SSLP tokens to deposit. + * @notice Only callable by the user or a CDPManager. + * @notice Emits a Deposit event upon successful deposit. */ function deposit(address _user, uint256 _amount) public override nonReentrant { require(_amount > 0, "Unit Protocol Wrapped Assets: INVALID_AMOUNT"); @@ -140,8 +174,11 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @notice Unwrap tokens, withdraw from TopDog and send them to user - * @dev only user or CDPManager could call this method + * @dev Withdraws SSLP tokens from TopDog and unwraps the tokens. + * @param _user Address of the user making the withdrawal. + * @param _amount Amount of SSLP tokens to withdraw. + * @notice Only callable by the user or a CDPManager. + * @notice Emits a Withdraw event upon successful withdrawal. */ function withdraw(address _user, uint256 _amount) public override nonReentrant { require(_amount > 0, "Unit Protocol Wrapped Assets: INVALID_AMOUNT"); @@ -160,9 +197,12 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @notice Manually move position (or its part) to another user (for example in case of liquidation) - * @dev Important! Use only with additional token transferring outside this function (example: liquidation - tokens are in vault and transferred by vault) - * @dev only CDPManager could call this method + * @dev Moves a position or its part to another user, typically used in liquidation scenarios. + * @param _userFrom Address of the user from whom the position is moved. + * @param _userTo Address of the user to whom the position is moved. + * @param _amount Amount of the position to be moved. + * @notice Only callable by the CDPManager. + * @notice Emits PositionMoved event upon successful position transfer. */ function movePosition(address _userFrom, address _userTo, uint256 _amount) public override nonReentrant hasVaultAccess { require(_userFrom != address(vault) && _userTo != address(vault), "Unit Protocol Wrapped Assets: NOT_ALLOWED_FOR_VAULT"); @@ -183,8 +223,9 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @notice Calculates pending reward for user. Not taken into account unclaimed reward from BoneLockers. - * @notice Use getClaimableRewardFromBoneLocker to calculate unclaimed reward from BoneLockers + * @dev Calculates the pending reward for a given user. + * @param _user Address of the user for whom to calculate the reward. + * @return uint256 Amount of the pending reward for the user. */ function pendingReward(address _user) public override view returns (uint256) { WSSLPUserProxy userProxy = usersProxies[_user]; @@ -196,8 +237,9 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @notice Claim pending direct reward for user. - * @notice Use claimRewardFromBoneLockers claim reward from BoneLockers + * @dev Claims the reward for a given user. + * @param _user Address of the user claiming the reward. + * @notice Only callable by the user. */ function claimReward(address _user) public override nonReentrant { require(_user == msg.sender, "Unit Protocol Wrapped Assets: AUTH_FAILED"); @@ -207,9 +249,10 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @notice Get claimable amount from BoneLocker - * @param _user user address - * @param _boneLocker BoneLocker to check, pass zero address to check current + * @dev Retrieves the claimable amount of reward from a specified BoneLocker. + * @param _user Address of the user. + * @param _boneLocker Address of the BoneLocker contract. + * @return uint256 Claimable amount of reward from the BoneLocker. */ function getClaimableRewardFromBoneLocker(address _user, IBoneLocker _boneLocker) public view returns (uint256) { WSSLPUserProxy userProxy = usersProxies[_user]; @@ -232,8 +275,8 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @notice get SSLP token - * @dev not immutable since it could be changed in TopDog + * @dev Retrieves the underlying SSLP token. + * @return IERC20 Address of the underlying SSLP token. */ function getUnderlyingToken() public override view returns (IERC20) { (IERC20 _sslpToken,,,) = topDog.poolInfo(topDogPoolId); @@ -257,6 +300,11 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { emit EmergencyWithdraw(msg.sender, amount); } + /** + * @dev Withdraws a specified token from the user proxy to the user. + * @param _token Address of the token to withdraw. + * @param _amount Amount of the token to withdraw. + */ function withdrawToken(address _token, uint _amount) public nonReentrant { WSSLPUserProxy userProxy = _requireUserProxy(msg.sender); userProxy.withdrawToken(_token, msg.sender, _amount, feeReceiver, feePercent); @@ -264,11 +312,24 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { emit TokenWithdraw(msg.sender, _token, _amount); } + /** + * @dev Reads data from a specified BoneLocker. + * @param _user Address of the user. + * @param _boneLocker Address of the BoneLocker. + * @param _callData Calldata for the BoneLocker read. + * @return (bool, bytes) Indicates if the operation was successful, and the returned data. + */ function readBoneLocker(address _user, address _boneLocker, bytes calldata _callData) public view returns (bool success, bytes memory data) { WSSLPUserProxy userProxy = _requireUserProxy(_user); (success, data) = userProxy.readBoneLocker(_boneLocker, _callData); } + /** + * @dev Calls a method on a specified BoneLocker. + * @param _boneLocker Address of the BoneLocker. + * @param _callData Calldata for the BoneLocker call. + * @return (bool, bytes) Indicates if the operation was successful, and the returned data. + */ function callBoneLocker(address _boneLocker, bytes calldata _callData) public nonReentrant returns (bool success, bytes memory data) { bytes4 selector; assembly { @@ -281,7 +342,10 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @dev Get sslp token for using in constructor + * @dev Retrieves the SSLP token address used in the constructor. + * @param _topDog Reference to the TopDog contract. + * @param _topDogPoolId Pool ID in the TopDog contract. + * @return address Address of the SSLP token. */ function getSsLpToken(ITopDog _topDog, uint256 _topDogPoolId) private view returns (address) { (IERC20 _sslpToken,,,) = _topDog.poolInfo(_topDogPoolId); @@ -290,46 +354,74 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** - * @dev Get symbol of sslp token for using in constructor + * @dev Retrieves the symbol of the SSLP token used in the constructor. + * @param _topDog Reference to the TopDog contract. + * @param _topDogPoolId Pool ID in the TopDog contract. + * @return string The symbol of the SSLP token. */ function getSsLpTokenSymbol(ITopDog _topDog, uint256 _topDogPoolId) private view returns (string memory) { return IERC20WithOptional(getSsLpToken(_topDog, _topDogPoolId)).symbol(); } /** - * @dev Get name of sslp token for using in constructor + * @dev Retrieves the name of the SSLP token used in the constructor. + * @param _topDog Reference to the TopDog contract. + * @param _topDogPoolId Pool ID in the TopDog contract. + * @return string The name of the SSLP token. */ function getSsLpTokenName(ITopDog _topDog, uint256 _topDogPoolId) private view returns (string memory) { return IERC20WithOptional(getSsLpToken(_topDog, _topDogPoolId)).name(); } /** - * @dev Get token0 symbol of sslp token for using in constructor + * @dev Retrieves the symbol of the token0 of the SSLP token used in the constructor. + * @param _topDog Reference to the TopDog contract. + * @param _topDogPoolId Pool ID in the TopDog contract. + * @return string The symbol of the token0 of the SSLP token. */ function getSsLpTokenToken0Symbol(ITopDog _topDog, uint256 _topDogPoolId) private view returns (string memory) { return IERC20WithOptional(address(ISushiSwapLpToken(getSsLpToken(_topDog, _topDogPoolId)).token0())).symbol(); } /** - * @dev Get token1 symbol of sslp token for using in constructor + * @dev Retrieves the symbol of the token1 of the SSLP token used in the constructor. + * @param _topDog Reference to the TopDog contract. + * @param _topDogPoolId Pool ID in the TopDog contract. + * @return string The symbol of the token1 of the SSLP token. */ function getSsLpTokenToken1Symbol(ITopDog _topDog, uint256 _topDogPoolId) private view returns (string memory) { return IERC20WithOptional(address(ISushiSwapLpToken(getSsLpToken(_topDog, _topDogPoolId)).token1())).symbol(); } /** - * @dev No direct transfers between users allowed since we store positions info in userInfo. + * @dev Internal function to handle token transfers, restricting direct transfers between users. + * @param sender Address sending the tokens. + * @param recipient Address receiving the tokens. + * @param amount Amount of tokens to transfer. + * @notice Transfers are only allowed to and from the vault contract. */ function _transfer(address sender, address recipient, uint256 amount) internal override onlyVault { require(sender == address(vault) || recipient == address(vault), "Unit Protocol Wrapped Assets: AUTH_FAILED"); super._transfer(sender, recipient, amount); } + /** + * @dev Internal function to require the existence of a user proxy. + * @param _user Address of the user to check. + * @return WSSLPUserProxy Returns the user proxy. + * @notice Reverts if the user proxy does not exist. + */ function _requireUserProxy(address _user) internal view returns (WSSLPUserProxy userProxy) { userProxy = usersProxies[_user]; require(address(userProxy) != address(0), "Unit Protocol Wrapped Assets: NO_DEPOSIT"); } + /** + * @dev Internal function to get or create a user proxy. + * @param _user Address of the user. + * @param sslpToken SSLP token for which the proxy is created. + * @return WSSLPUserProxy Returns the newly created or existing user proxy. + */ function _getOrCreateUserProxy(address _user, IERC20 sslpToken) internal returns (WSSLPUserProxy userProxy) { userProxy = usersProxies[_user]; if (address(userProxy) == address(0)) { @@ -342,7 +434,10 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { } /** + * @dev Internal function to create a clone of a target contract. * @dev see https://github.com/optionality/clone-factory/blob/master/contracts/CloneFactory.sol + * @param target Address of the target contract to clone. + * @return address Returns the address of the newly created clone. */ function createClone(address target) internal returns (address result) { bytes20 targetBytes = bytes20(target); @@ -354,4 +449,5 @@ contract WrappedShibaSwapLp is IWrappedAsset, Auth2, ERC20, ReentrancyGuard { result := create(0, clone, 0x37) } } + } diff --git a/contracts/wrapped-assets/test-helpers/BoneLocker_Mock.sol b/contracts/wrapped-assets/test-helpers/BoneLocker_Mock.sol index b4619ed..8791b53 100644 --- a/contracts/wrapped-assets/test-helpers/BoneLocker_Mock.sol +++ b/contracts/wrapped-assets/test-helpers/BoneLocker_Mock.sol @@ -10,15 +10,17 @@ import "@openzeppelin/contracts/math/SafeMath.sol"; import "../../interfaces/wrapped-assets/IBoneLocker.sol"; - -// BoneToken locker contract. +/** + * @title BoneLocker_Mock + * @dev Implementation of the IBoneLocker interface to create a mock BoneToken locker contract. + */ contract BoneLocker_Mock is IBoneLocker, Ownable { using SafeMath for uint256; IERC20 boneToken; address emergencyAddress; bool emergencyFlag = false; - struct LockInfo{ + struct LockInfo { uint256 _amount; uint256 _timestamp; bool _isDev; @@ -33,6 +35,13 @@ contract BoneLocker_Mock is IBoneLocker, Ownable { event LockingPeriod(address indexed user, uint newLockingPeriod, uint newDevLockingPeriod); + /** + * @dev Sets the initial values for {_boneToken}, {emergencyAddress}, {lockingPeriod}, and {devLockingPeriod}. + * @param _boneToken The address of the BoneToken. + * @param _emergencyAddress The address that can trigger the emergency mode. + * @param _lockingPeriodInDays The number of days for the normal locking period. + * @param _devLockingPeriodInDays The number of days for the developer locking period. + */ constructor(address _boneToken, address _emergencyAddress, uint256 _lockingPeriodInDays, uint256 _devLockingPeriodInDays) { require(address(_boneToken) != address(0), "_bone token is a zero address"); require(address(_emergencyAddress) != address(0), "_emergencyAddress is a zero address"); @@ -42,7 +51,12 @@ contract BoneLocker_Mock is IBoneLocker, Ownable { devLockingPeriod = _devLockingPeriodInDays * 1 days; } - // function to lock user reward bone tokens in token contract, called by onlyOwner that would be TopDog.sol + /** + * @dev Locks a given amount of BoneToken for a specified user. + * @param _holder The address of the user whose tokens are to be locked. + * @param _amount The amount of tokens to be locked. + * @param _isDev A boolean to indicate if the locking is for a developer. + */ function lock(address _holder, uint256 _amount, bool _isDev) external override onlyOwner { require(_holder != address(0), "Invalid user address"); require(_amount > 0, "Invalid amount entered"); @@ -51,20 +65,25 @@ contract BoneLocker_Mock is IBoneLocker, Ownable { unclaimedTokensByUser[_holder] = unclaimedTokensByUser[_holder].add(_amount); } - // function to claim all the tokens locked for a user, after the locking period + /** + * @dev Claims all the tokens locked for a user after the locking period. + * @param r The upper boundary of the range of LockInfo entries to claim for the user. + * @param user The address of the user for whom to claim tokens. + */ function claimAllForUser(uint256 r, address user) public override { require(!emergencyFlag, "Emergency mode, cannot access this function"); require(r>latestCounterByUser[user], "Increase right header, already claimed till this"); require(r<=lockInfoByUser[user].length, "Decrease right header, it exceeds total length"); + LockInfo[] memory lockInfoArrayForUser = lockInfoByUser[user]; uint256 totalTransferableAmount = 0; uint i; for (i=latestCounterByUser[user]; i= (lockInfoArrayForUser[i]._timestamp.add(lockingPeriodHere))){ + if (block.timestamp >= (lockInfoArrayForUser[i]._timestamp.add(lockingPeriodHere))) { totalTransferableAmount = totalTransferableAmount.add(lockInfoArrayForUser[i]._amount); unclaimedTokensByUser[user] = unclaimedTokensByUser[user].sub(lockInfoArrayForUser[i]._amount); latestCounterByUser[user] = i.add(1); @@ -75,55 +94,78 @@ contract BoneLocker_Mock is IBoneLocker, Ownable { boneToken.transfer(user, totalTransferableAmount); } - // function to claim all the tokens locked by user, after the locking period + /** + * @dev Claims all the tokens locked by the sender after the locking period. + * @param r The upper boundary of the range of LockInfo entries to claim for the sender. + */ function claimAll(uint256 r) external override { claimAllForUser(r, msg.sender); } - // function to get claimable amount for any user - function getClaimableAmount(address _user) external override view returns(uint256) { + /** + * @dev Returns the amount of tokens that are claimable for a user. + * @param _user The address of the user to check claimable amount for. + * @return totalTransferableAmount The total amount of tokens that can be claimed by the user. + */ + function getClaimableAmount(address _user) external override view returns (uint256 totalTransferableAmount) { LockInfo[] memory lockInfoArrayForUser = lockInfoByUser[_user]; uint256 totalTransferableAmount = 0; uint i; for (i=latestCounterByUser[_user]; i= (lockInfoArrayForUser[i]._timestamp.add(lockingPeriodHere))){ + if (block.timestamp >= (lockInfoArrayForUser[i]._timestamp.add(lockingPeriodHere))) { totalTransferableAmount = totalTransferableAmount.add(lockInfoArrayForUser[i]._amount); } else { break; } } - return totalTransferableAmount; } - // get the left and right headers for a user, left header is the index counter till which we have already iterated, right header is basically the length of user's lockInfo array - function getLeftRightCounters(address _user) external override view returns(uint256, uint256){ - return(latestCounterByUser[_user], lockInfoByUser[_user].length); + /** + * @dev Returns the left and right counters for a user's lockInfo array. + * @param _user The address of the user to check the counters for. + * @return The left and right counters for the user's lockInfo array. + */ + function getLeftRightCounters(address _user) external override view returns (uint256, uint256) { + return (latestCounterByUser[_user], lockInfoByUser[_user].length); } - // in cases of emergency, emergency address can set this to true, which will enable emergencyWithdraw function + /** + * @dev Sets the emergency flag to enable or disable emergency functions. + * @param _emergencyFlag The new value of the emergency flag. + */ function setEmergencyFlag(bool _emergencyFlag) external { require(msg.sender == emergencyAddress, "This function can only be called by emergencyAddress"); emergencyFlag = _emergencyFlag; } - // function for owner to transfer all tokens to another address - function emergencyWithdrawOwner(address _to) external override onlyOwner{ + /** + * @dev Allows the owner to withdraw all tokens to another address in case of emergency. + * @param _to The address to which the tokens will be transferred. + */ + function emergencyWithdrawOwner(address _to) external override onlyOwner { uint256 amount = boneToken.balanceOf(address(this)); require(boneToken.transfer(_to, amount), 'MerkleDistributor: Transfer failed.'); } - // emergency address can be updated from here + /** + * @dev Updates the emergency address. + * @param _newAddr The new emergency address. + */ function setEmergencyAddr(address _newAddr) external { require(msg.sender == emergencyAddress, "This function can only be called by emergencyAddress"); require(_newAddr != address(0), "_newAddr is a zero address"); emergencyAddress = _newAddr; } - // function to update/change the normal & dev locking period + /** + * @dev Updates the locking periods for normal and developer locks. + * @param _newLockingPeriod The new normal locking period in seconds. + * @param _newDevLockingPeriod The new developer locking period in seconds. + */ function setLockingPeriod(uint256 _newLockingPeriod, uint256 _newDevLockingPeriod) external override onlyOwner { lockingPeriod = _newLockingPeriod; devLockingPeriod = _newDevLockingPeriod; diff --git a/contracts/wrapped-assets/test-helpers/BoneToken_Mock.sol b/contracts/wrapped-assets/test-helpers/BoneToken_Mock.sol index d9f35d0..6197eae 100644 --- a/contracts/wrapped-assets/test-helpers/BoneToken_Mock.sol +++ b/contracts/wrapped-assets/test-helpers/BoneToken_Mock.sol @@ -8,15 +8,29 @@ import "@openzeppelin/contracts/access/Ownable.sol"; import "../../interfaces/wrapped-assets/IBoneToken.sol"; - -// BoneToken with Governance. +/** + * @title BoneToken_Mock + * @dev Implementation of the IBoneToken interface with ERC20 token standard and Ownable features. + * This token is used for testing purposes and includes governance capabilities. + */ contract BoneToken_Mock is IBoneToken, ERC20("BONE SHIBASWAP", "BONE"), Ownable { using SafeMath for uint256; - /// @notice Creates `_amount` token to `_to`. Must only be called by the owner (TopDog). + /** + * @dev Mints `_amount` tokens to address `_to`. + * Must only be called by the contract owner (TopDog). + * @param _to The address of the beneficiary that will receive the tokens. + * @param _amount The number of tokens to mint. + */ function mint(address _to, uint256 _amount) public override onlyOwner { _mint(_to, _amount); } + /** + * @dev Mints `_amount` tokens to address `_to` without access restriction. + * This function is meant for testing purposes. + * @param _to The address of the beneficiary that will receive the tokens. + * @param _amount The number of tokens to mint. + */ function testMint(address _to, uint256 _amount) public { _mint(_to, _amount); } diff --git a/contracts/wrapped-assets/test-helpers/MigratorShib_Mock.sol b/contracts/wrapped-assets/test-helpers/MigratorShib_Mock.sol index b671f6e..f2a64e8 100644 --- a/contracts/wrapped-assets/test-helpers/MigratorShib_Mock.sol +++ b/contracts/wrapped-assets/test-helpers/MigratorShib_Mock.sol @@ -7,16 +7,30 @@ pragma solidity 0.7.6; import "./TopDog_Mock.sol"; - +/** + * @title MigratorShib_Mock + * @dev Mock contract for token migration. + * This contract is only for testing purposes and simulates the migration process. + */ contract MigratorShib_Mock is IMigratorShib { + /// @notice The token that users will receive after the migration. IERC20 public newToken; + /** + * @dev Migrates the user's balance of the given token to the new token. + * @param token The token to migrate from. + * @return IERC20 The new token instance. + */ function migrate(IERC20 token) external override returns (IERC20) { newToken.transfer(msg.sender, token.balanceOf(msg.sender)); return newToken; } + /** + * @dev Sets the new token to which the old tokens will be migrated. + * @param token The new token contract address. + */ function setNewToken(IERC20 token) public { newToken = token; } diff --git a/contracts/wrapped-assets/test-helpers/SushiSwapLpToken_Mock.sol b/contracts/wrapped-assets/test-helpers/SushiSwapLpToken_Mock.sol index b07a2fb..8e888bb 100644 --- a/contracts/wrapped-assets/test-helpers/SushiSwapLpToken_Mock.sol +++ b/contracts/wrapped-assets/test-helpers/SushiSwapLpToken_Mock.sol @@ -9,11 +9,27 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "../../interfaces/wrapped-assets/ISushiSwapLpToken.sol"; - +/** + * @title SushiSwapLpToken_Mock + * @dev Mock implementation of a SushiSwap liquidity pool token for testing purposes. + * Inherits from ERC20 and implements ISushiSwapLpToken interface. + */ contract SushiSwapLpToken_Mock is ERC20, ISushiSwapLpToken { + /// @notice Address of the first token in the liquidity pair. address public override token0; + + /// @notice Address of the second token in the liquidity pair. address public override token1; + /** + * @dev Sets the initial values for token0, token1, name, symbol, and decimals. + * Mints 100 tokens to the address deploying the contract. + * @param _token0 The address of the first token in the liquidity pair. + * @param _token1 The address of the second token in the liquidity pair. + * @param name_ The name of the liquidity pool token. + * @param symbol_ The symbol of the liquidity pool token. + * @param decimals_ The number of decimals the liquidity pool token uses. + */ constructor (address _token0, address _token1, string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {