Skip to content
2 changes: 1 addition & 1 deletion contracts/events/ProtocolSettingsEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ contract ProtocolSettingsEvents is ModulesCommonEvents {
uint256 lendingAmount,
uint256 tradingAmount,
uint256 borrowingAmount,
uint256 wRBTCConverted
uint256 wrappedNativeTokenConverted
);

event WithdrawLendingFees(
Expand Down
440 changes: 212 additions & 228 deletions contracts/governance/FeeSharingCollector/FeeSharingCollector.sol

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "../../interfaces/IERC20.sol";
import "../IFeeSharingCollector.sol";
import "../Staking/interfaces/IStaking.sol";
import "../../mixins/EnumerableAddressSet.sol";
import "../../interfaces/IWrbtcERC20.sol";
import "../../interfaces/IWrappedNativeTokenERC20.sol";

/**
* @title FeeSharingCollectorStorage contact
Expand All @@ -16,6 +16,7 @@ import "../../interfaces/IWrbtcERC20.sol";
contract FeeSharingCollectorStorage is Ownable {
using EnumerableAddressSet for EnumerableAddressSet.AddressSet;
uint256 constant FEE_WITHDRAWAL_INTERVAL = 172800;
uint32 constant MAX_CHECKPOINTS = 100;

IProtocol public protocol;
IStaking public staking;
Expand Down Expand Up @@ -79,12 +80,17 @@ contract FeeSharingCollectorStorage is Ownable {
/**
* @dev Wrapped native token address
*/
address public wrbtcTokenAddress;
address public wrappedNativeTokenAddress;

/**
* @dev Wrapped native token loan token address
*/
address public loanTokenWrbtcAddress;
address public loanWrappedNativeTokenAddress;

/**
* @dev sovryn lb dex factory address
*/
address public sovrynLBDexFactoryAddress;

/**
* @dev Prevents a contract from calling itself, directly or indirectly.
Expand All @@ -100,6 +106,16 @@ contract FeeSharingCollectorStorage is Ownable {
_;
reentrancyLock = REENTRANCY_GUARD_FREE;
}

/* Modifier */
modifier oneTimeExecution(bytes4 _funcSig) {
require(
!isFunctionExecuted[_funcSig],
"FeeSharingCollector: function can only be called once"
);
_;
isFunctionExecuted[_funcSig] = true;
}
}

/* Interfaces */
Expand All @@ -110,16 +126,16 @@ interface IProtocol {
* @param tokens The array address of the token instance.
* @param receiver The address of the withdrawal recipient.
*
* @return The withdrawn total amount in wRBTC
* @return The withdrawn total amount in wrappedNativeToken
* */
function withdrawFees(
address[] calldata tokens,
address receiver
) external returns (uint256 totalWRBTCWithdrawn);
) external returns (uint256 totalWrappedNativeTokenWithdrawn);

function underlyingToLoanPool(address token) external view returns (address);

function wrbtcToken() external view returns (IWrbtcERC20);
function wrappedNativeToken() external view returns (IWrappedNativeTokenERC20);

function getSovTokenAddress() external view returns (address);
}
19 changes: 19 additions & 0 deletions contracts/governance/IFeeSharingCollectorMultiToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity ^0.5.17;

/**
* @title Interface for contract governance/FeeSharingCollector/FeeSharingCollector.sol
* @dev Interfaces are used to cast a contract address into a callable instance.
* */
interface IFeeSharingCollectorMultiToken {
function withdrawFees(address[] calldata _token) external;

function transferTokens(address _token, uint96 _amount) external;

function withdraw(address _token, uint32 _maxCheckpoint, address _receiver) external;

function withdrawTokens(
address[] calldata _tokens,
uint32[] calldata _maxCheckpoints,
address _receiver
) external;
}
9 changes: 9 additions & 0 deletions contracts/interfaces/ISovrynLBFactoryDex.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pragma solidity 0.5.17;

interface ISovrynLBFactoryDex {
function getNumberOfLBPairs() external view returns (uint256);

function getLBPairAtIndex(uint256 id) external returns (address);

function getFeeRecipient() external view returns (address);
}
11 changes: 11 additions & 0 deletions contracts/interfaces/ISovrynLBPairDex.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pragma solidity 0.5.17;

interface ISovrynLBPairDex {
function getProtocolFees() external view returns (uint128 protocolFeeX, uint128 protocolFeeY);

function collectProtocolFees() external returns (bytes32 collectedProtocolFees);

function getTokenX() external view returns (address tokenX);

function getTokenY() external view returns (address tokenY);
}
12 changes: 12 additions & 0 deletions contracts/interfaces/IWrappedNativeToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Copyright 2017-2020, bZeroX, LLC. All Rights Reserved.
* Licensed under the Apache License, Version 2.0.
*/

pragma solidity >=0.5.0 <0.6.0;

interface IWrappedNativeToken {
function deposit() external payable;

function withdraw(uint256 wad) external;
}
11 changes: 11 additions & 0 deletions contracts/interfaces/IWrappedNativeTokenERC20.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* Copyright 2017-2020, bZeroX, LLC. All Rights Reserved.
* Licensed under the Apache License, Version 2.0.
*/

pragma solidity >=0.5.0 <0.6.0;

import "./IWrappedNativeToken.sol";
import "./IERC20.sol";

contract IWrappedNativeTokenERC20 is IWrappedNativeToken, IERC20 {}
4 changes: 2 additions & 2 deletions contracts/mockup/FeeSharingCollectorMockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,12 @@ contract FeeSharingCollectorMockup is FeeSharingCollector {
return _getEndOfRange(0, _token, 0);
}

function getRBTCBalance(
function getNativeTokenBalance(
address _token,
address _user,
uint32 _maxCheckpoints
) public view returns (uint256 _tokenAmount, uint256 _endToken) {
return _getRBTCBalance(_token, _user, _maxCheckpoints);
return _getNativeTokenBalance(_token, _user, _maxCheckpoints);
}

function testWithdrawReentrancy(
Expand Down
42 changes: 42 additions & 0 deletions contracts/mockup/FeeSharingCollectorMultipleTokenMockup.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
pragma solidity ^0.5.17;

import "../governance/FeeSharingCollector/FeeSharingCollectorMultiToken.sol";

contract FeeSharingCollectorMultiTokenMockup is FeeSharingCollectorMultiToken {
struct TestData {
address loanPoolToken;
uint32 maxCheckpoints;
address receiver;
}

TestData public testData;

constructor(IProtocol _protocol, IStaking _staking) public {
protocol = _protocol;
staking = _staking;
}

function withdraw(address _token, uint32 _maxCheckpoint, address _receiver) public {
testData = TestData(_token, _maxCheckpoint, _receiver);
}

function trueWithdraw(address _token, uint32 _maxCheckpoint, address _receiver) public {
super.withdraw(_token, _maxCheckpoint, _receiver);
}

function trueWithdrawTokens(
address[] memory _tokens,
uint32[] memory _maxCheckpoints,
address _receiver
) public {
super.withdrawTokens(_tokens, _maxCheckpoints, _receiver);
}

function addCheckPoint(address loanPoolToken, uint256 poolTokenAmount) public {
uint96 amount96 = safe96(
poolTokenAmount,
"FeeSharingProxy::withdrawFees: pool token amount exceeds 96 bits"
);
_addCheckpoint(loanPoolToken, amount96);
}
}
34 changes: 34 additions & 0 deletions contracts/mockup/MockSovrynLBFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
pragma solidity 0.5.17;

import "../interfaces/IERC20.sol";
import "../governance/IFeeSharingCollectorMultiToken.sol";

contract MockSovrynLBFactory {
address feeRecipient;
uint256 totalPairs;
address[] lbPairs;

constructor() public {}

function getFeeRecipient() public returns (address) {
return feeRecipient;
}

function setFeeRecipient(address _feeRecipient) public {
feeRecipient = _feeRecipient;
}

function addLbPairs(uint256 _totalPairs, address[] memory _lbPairs) public {
require(_totalPairs == _lbPairs.length, "mismatch lbPairs length");
totalPairs = _totalPairs;
lbPairs = _lbPairs;
}

function getNumberOfLBPairs() public view returns (uint256) {
return totalPairs;
}

function getLBPairAtIndex(uint256 _id) public view returns (address) {
return lbPairs[_id];
}
}
53 changes: 53 additions & 0 deletions contracts/mockup/MockSovrynLBPair.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
pragma solidity 0.5.17;

import "../interfaces/IERC20.sol";
import "../governance/IFeeSharingCollectorMultiToken.sol";
import "../interfaces/ISovrynLBFactoryDex.sol";

contract MockSovrynLBPair {
address lbFactory;
address tokenX;
address tokenY;

uint128 amountTokenX;
uint128 amountTokenY;

modifier onlyFeeRecipient() {
require(
ISovrynLBFactoryDex(lbFactory).getFeeRecipient() == msg.sender,
"Only feeRecipient"
);
_;
}

function getTokenX() public returns (address _tokenX) {
return tokenX;
}

function getTokenY() public returns (address _tokenY) {
return tokenY;
}

constructor(
address _lbFactory,
address _tokenX,
address _tokenY,
uint128 _amountTokenX,
uint128 _amountTokenY
) public {
tokenX = _tokenX;
tokenY = _tokenY;
amountTokenX = _amountTokenX;
amountTokenY = _amountTokenY;
lbFactory = _lbFactory;
}

function getProtocolFees() public view returns (uint128 protocolFeeX, uint128 protocolFeeY) {
return (amountTokenX, amountTokenY);
}

function collectProtocolFees() public onlyFeeRecipient returns (bytes32) {
IERC20(tokenX).transfer(msg.sender, amountTokenX);
IERC20(tokenY).transfer(msg.sender, amountTokenY);
}
}
Loading