Skip to content

Commit

Permalink
Merge 33420a5 into 2db5c51
Browse files Browse the repository at this point in the history
  • Loading branch information
anon-xxs committed Jun 30, 2021
2 parents 2db5c51 + 33420a5 commit cc29980
Show file tree
Hide file tree
Showing 43 changed files with 812 additions and 133 deletions.
1 change: 0 additions & 1 deletion contracts/connectors/loantoken/LoanTokenLogicLM.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,4 @@ contract LoanTokenLogicLM is LoanTokenLogicStandard {
_safeTransfer(loanTokenAddress, receiver, redeemed, "asset transfer failed");
}
}

}
56 changes: 43 additions & 13 deletions contracts/connectors/loantoken/LoanTokenLogicStandard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
* @notice Fallback function is to react to receiving value (rBTC).
* */
function() external {
revert("loan token logic - fallback not allowed");
// Due to contract size issue, need to keep the error message to 32 bytes length / we remove the revert function
// Remove revert function is fine as this fallback function is not payable, but the trade off is we cannot have the custom message for the fallback function error
// revert("loan token-fallback not allowed");
}

/* Public functions */
Expand Down Expand Up @@ -215,12 +217,15 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
/// Temporary: limit transaction size.
if (transactionLimit[collateralTokenAddress] > 0) require(collateralTokenSent <= transactionLimit[collateralTokenAddress]);

require(msg.value == 0 || msg.value == collateralTokenSent, "7");
require(collateralTokenSent != 0 || loanId != 0, "8");
require(collateralTokenAddress != address(0) || msg.value != 0 || loanId != 0, "9");
require( (msg.value == 0 || msg.value == collateralTokenSent) && (collateralTokenSent != 0 || loanId != 0) && (collateralTokenAddress != address(0) || msg.value != 0 || loanId != 0) && (loanId == 0 || msg.sender == borrower), "7");

/// @dev We have an issue regarding contract size code is too big. 1 of the solution is need to keep the error message 32 bytes length
// Temporarily, we combine this require to the above, so can save the contract size code
// require(collateralTokenSent != 0 || loanId != 0, "8");
// require(collateralTokenAddress != address(0) || msg.value != 0 || loanId != 0, "9");

/// @dev Ensure authorized use of existing loan.
require(loanId == 0 || msg.sender == borrower, "unauthorized use of existing loan");
// require(loanId == 0 || msg.sender == borrower, "401 use of existing loan");

if (collateralTokenAddress == address(0)) {
collateralTokenAddress = wrbtcTokenAddress;
Expand Down Expand Up @@ -303,6 +308,7 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
uint256 collateralTokenSent,
address collateralTokenAddress,
address trader,
uint256 minReturn, // minimum position size in the collateral tokens
bytes memory loanDataBytes /// Arbitrary order data.
)
public
Expand All @@ -315,14 +321,16 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
{
_checkPause();

checkPriceDivergence(leverageAmount, loanTokenSent, collateralTokenSent, collateralTokenAddress, minReturn);

if (collateralTokenAddress == address(0)) {
collateralTokenAddress = wrbtcTokenAddress;
}

require(collateralTokenAddress != loanTokenAddress, "11");

/// @dev Ensure authorized use of existing loan.
require(loanId == 0 || msg.sender == trader, "unauthorized use of existing loan");
require(loanId == 0 || msg.sender == trader, "401 use of existing loan");

/// Temporary: limit transaction size.
if (transactionLimit[collateralTokenAddress] > 0) require(collateralTokenSent <= transactionLimit[collateralTokenAddress]);
Expand Down Expand Up @@ -374,6 +382,7 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
uint256 collateralTokenSent,
address collateralTokenAddress,
address trader,
uint256 minReturn, // minimum position size in the collateral tokens
address affiliateReferrer, // the user was brought by the affiliate (referrer)
bytes calldata loanDataBytes // arbitrary order data
)
Expand All @@ -386,7 +395,17 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
{
if (affiliateReferrer != address(0))
ProtocolAffiliatesInterface(sovrynContractAddress).setAffiliatesReferrer(trader, affiliateReferrer);
return marginTrade(loanId, leverageAmount, loanTokenSent, collateralTokenSent, collateralTokenAddress, trader, loanDataBytes);
return
marginTrade(
loanId,
leverageAmount,
loanTokenSent,
collateralTokenSent,
collateralTokenAddress,
trader,
minReturn,
loanDataBytes
);
}

/**
Expand Down Expand Up @@ -707,7 +726,7 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
uint256 leverageAmount,
uint256 loanTokenSent,
uint256 collateralTokenSent,
address collateralTokenAddress /// address(0) means rBTC.
address collateralTokenAddress // address(0) means ETH
)
public
view
Expand Down Expand Up @@ -817,6 +836,18 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
}
}

function checkPriceDivergence(
uint256 leverageAmount,
uint256 loanTokenSent,
uint256 collateralTokenSent,
address collateralTokenAddress,
uint256 minReturn
) public view {
(, uint256 estimatedCollateral, ) =
getEstimatedMarginDetails(leverageAmount, loanTokenSent, collateralTokenSent, collateralTokenAddress);
require(estimatedCollateral >= minReturn, "coll too low");
}

/* Internal functions */

/**
Expand Down Expand Up @@ -943,7 +974,7 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
/// @dev Get the oracle rate from collateral -> loan
(uint256 collateralToLoanRate, uint256 collateralToLoanPrecision) =
FeedsLike(ProtocolLike(sovrynContractAddress).priceFeeds()).queryRate(collateralTokenAddress, loanTokenAddress);
require((collateralToLoanRate != 0) && (collateralToLoanPrecision != 0), "invalid exchange rate for the collateral token");
require((collateralToLoanRate != 0) && (collateralToLoanPrecision != 0), "invalid rate collateral token");

/// @dev Compute the loan token amount with the oracle rate.
uint256 loanTokenAmount = collateralTokenSent.mul(collateralToLoanRate).div(collateralToLoanPrecision);
Expand Down Expand Up @@ -1317,7 +1348,7 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
uint256 thisMaxScaleRate = maxScaleRate;

if (utilRate < thisTargetLevel) {
/// @dev Target targetLevel utilization when utilization is under targetLevel
// target targetLevel utilization when utilization is under targetLevel
utilRate = thisTargetLevel;
}

Expand Down Expand Up @@ -1481,8 +1512,8 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
}

function _burnFromLM(uint256 burnAmount) internal returns (uint256) {
uint balanceOnLM = ILiquidityMining(liquidityMiningAddress).getUserPoolTokenBalance(address(this), msg.sender);
require(balanceOnLM.add(balanceOf(msg.sender)) >= burnAmount, "not enough balance");
uint256 balanceOnLM = ILiquidityMining(liquidityMiningAddress).getUserPoolTokenBalance(address(this), msg.sender);
require(balanceOnLM.add(balanceOf(msg.sender)) >= burnAmount, "invalid balance"); // invalid balance

if (balanceOnLM > 0) {
//withdraw pool tokens and LM rewards to the passed address
Expand All @@ -1495,5 +1526,4 @@ contract LoanTokenLogicStandard is LoanTokenSettingsLowerAdmin {
//burn the tokens of the msg.sender
return _burnToken(burnAmount);
}

}
2 changes: 1 addition & 1 deletion contracts/connectors/loantoken/LoanTokenLogicWrbtc.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
pragma solidity 0.5.17;
pragma experimental ABIEncoderV2;

import "./LoanTokenLogicLM.sol";
import "./LoanTokenLogicStandard.sol";

contract LoanTokenLogicWrbtc is LoanTokenLogicStandard {
function mintWithBTC(address receiver, bool useLM) external payable nonReentrant returns (uint256 mintAmount) {
Expand Down
13 changes: 7 additions & 6 deletions contracts/feeds/PriceFeeds.sol
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ contract PriceFeeds is Constants, Ownable {
if (globalPricingPaused) {
return 0;
}

(uint256 rate, uint256 precision) = _queryRate(sourceToken, destToken);

destAmount = sourceAmount.mul(rate).div(precision);
Expand Down Expand Up @@ -155,11 +156,9 @@ contract PriceFeeds is Constants, Ownable {

sourceToDestSwapRate = destAmount.mul(precision).div(sourceAmount);

uint256 spreadValue = sourceToDestSwapRate > rate ? sourceToDestSwapRate - rate : rate - sourceToDestSwapRate;

if (spreadValue != 0) {
if (rate > sourceToDestSwapRate) {
uint256 spreadValue = rate - sourceToDestSwapRate;
spreadValue = spreadValue.mul(10**20).div(sourceToDestSwapRate);

require(spreadValue <= maxSlippage, "price disagreement");
}
}
Expand Down Expand Up @@ -353,9 +352,11 @@ contract PriceFeeds is Constants, Ownable {
* @param isPaused The new status of pause (true/false).
* */
function setGlobalPricingPaused(bool isPaused) external onlyOwner {
globalPricingPaused = isPaused;
if (globalPricingPaused != isPaused) {
globalPricingPaused = isPaused;

emit GlobalPricingPaused(msg.sender, isPaused);
emit GlobalPricingPaused(msg.sender, isPaused);
}
}

/*
Expand Down
25 changes: 25 additions & 0 deletions contracts/interfaces/ISovryn.sol
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,31 @@ contract ISovryn is

function getLegacyOracle(address ref) external view returns (address);

////// Swaps External //////
function swapExternal(
address sourceToken,
address destToken,
address receiver,
address returnToSender,
uint256 sourceTokenAmount,
uint256 requiredDestTokenAmount,
uint256 minReturn,
bytes calldata swapData
) external returns (uint256 destTokenAmountReceived, uint256 sourceTokenAmountUsed);

function getSwapExpectedReturn(
address sourceToken,
address destToken,
uint256 sourceTokenAmount
) external view returns (uint256);

function checkPriceDivergence(
address sourceToken,
address destToken,
uint256 sourceTokenAmount,
uint256 minReturn
) public view;

////// Affiliates Module //////

function getUserNotFirstTradeFlag(address user) external view returns (bool);
Expand Down
102 changes: 102 additions & 0 deletions contracts/mockup/LockedSOVFailedMockup.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
pragma solidity ^0.5.17;

import "../openzeppelin/SafeMath.sol";
import "../interfaces/IERC20.sol";

/**
* @title An interface for the Locked SOV Contract.
* @author Franklin Richards - powerhousefrank@protonmail.com
* @dev This is not a complete interface of the Locked SOV Contract.
*/
contract LockedSOVFailedMockup {
using SafeMath for uint256;

/* Storage */

/// @notice The SOV token contract.
IERC20 public SOV;

/// @notice The user balances.
mapping(address => uint256) lockedBalances;
/// @notice The user balances.
mapping(address => bool) isAdmin;

/* Events */

/// @notice Emitted when a new Admin is added to the admin list.
/// @param _initiator The address which initiated this event to be emitted.
/// @param _newAdmin The address of the new admin.
event AdminAdded(address indexed _initiator, address indexed _newAdmin);

/// @notice Emitted when an admin is removed from the admin list.
/// @param _initiator The address which initiated this event to be emitted.
/// @param _removedAdmin The address of the removed admin.
event AdminRemoved(address indexed _initiator, address indexed _removedAdmin);

/* Modifiers */

modifier onlyAdmin {
require(isAdmin[msg.sender], "Only admin can call this.");
_;
}

/* Functions */

/**
* @notice Setup the required parameters.
* @param _SOV The SOV token address.
* @param _admins The list of admins to be added.
*/
constructor(address _SOV, address[] memory _admins) public {
require(_SOV != address(0), "Invalid SOV Address.");
SOV = IERC20(_SOV);
for (uint256 index = 0; index < _admins.length; index++) {
isAdmin[_admins[index]] = true;
}
}

/**
* @notice The function to add a new admin.
* @param _newAdmin The address of the new admin.
*/
function addAdmin(address _newAdmin) public onlyAdmin {
require(_newAdmin != address(0), "Invalid Address");
require(!isAdmin[_newAdmin], "Address is already admin");
isAdmin[_newAdmin] = true;

emit AdminAdded(msg.sender, _newAdmin);
}

/**
* @notice The function to remove an admin.
* @param _adminToRemove The address of the admin which should be removed.
*/
function removeAdmin(address _adminToRemove) public onlyAdmin {
require(isAdmin[_adminToRemove], "Address is not an admin");
isAdmin[_adminToRemove] = false;

emit AdminRemoved(msg.sender, _adminToRemove);
}

/**
* @notice Adds SOV to the locked balance of a user.
* @param _userAddress The user whose locked balance has to be updated with _sovAmount.
* @param _sovAmount The amount of SOV to be added to the locked balance.
*/
function depositSOV(address _userAddress, uint256 _sovAmount) external {
revert("For testing purposes");
bool txStatus = SOV.transferFrom(msg.sender, address(this), _sovAmount);
require(txStatus, "Token transfer was not successful. Check receiver address.");

lockedBalances[_userAddress] = lockedBalances[_userAddress].add(_sovAmount);
}

/**
* @notice The function to get the locked balance of a user.
* @param _addr The address of the user to check the locked balance.
* @return _balance The locked balance of the address `_addr`.
*/
function getLockedBalance(address _addr) public view returns (uint256 _balance) {
return lockedBalances[_addr];
}
}
5 changes: 2 additions & 3 deletions contracts/mockup/StakingMockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ contract StakingMockup is Staking {
}

/**
* @dev We need this function to simulate zero delegate checkpoint value.
*/
* @dev We need this function to simulate zero delegate checkpoint value.
*/
function setDelegateStake(
address delegatee,
uint256 lockedTS,
Expand All @@ -60,5 +60,4 @@ contract StakingMockup is Staking {
bytes32 codeHash = _getCodeHash(_contract);
return vestingCodeHashes[codeHash];
}

}
30 changes: 14 additions & 16 deletions contracts/mockup/VestingLogicMockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@ pragma experimental ABIEncoderV2;
import "../governance/Vesting/VestingLogic.sol";

contract VestingLogicMockup is VestingLogic {
/**
* @dev we had a bug in a loop: "i < endDate" instead of "i <= endDate"
*/
function delegate(address _delegatee) public onlyTokenOwner {
require(_delegatee != address(0), "delegatee address invalid");

/**
* @dev we had a bug in a loop: "i < endDate" instead of "i <= endDate"
*/
function delegate(address _delegatee) public onlyTokenOwner {
require(_delegatee != address(0), "delegatee address invalid");

/// @dev Withdraw for each unlocked position.
/// @dev Don't change FOUR_WEEKS to TWO_WEEKS, a lot of vestings already deployed with FOUR_WEEKS
/// workaround found, but it doesn't work with TWO_WEEKS
for (uint256 i = startDate + cliff; i < endDate; i += FOUR_WEEKS) {
staking.delegate(_delegatee, i);
}
emit VotesDelegated(msg.sender, _delegatee);
}

}
/// @dev Withdraw for each unlocked position.
/// @dev Don't change FOUR_WEEKS to TWO_WEEKS, a lot of vestings already deployed with FOUR_WEEKS
/// workaround found, but it doesn't work with TWO_WEEKS
for (uint256 i = startDate + cliff; i < endDate; i += FOUR_WEEKS) {
staking.delegate(_delegatee, i);
}
emit VotesDelegated(msg.sender, _delegatee);
}
}
Loading

0 comments on commit cc29980

Please sign in to comment.