Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SOV-2938 add wrbtc & iwrbtc address in feeSharing storage #519

Merged
merged 5 commits into from
Sep 20, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ typechain/
*/deployments/*forked*
venv/
!/external/artifacts/
cache_hardhat/
cache_hardhat/
128 changes: 67 additions & 61 deletions contracts/governance/FeeSharingCollector/FeeSharingCollector.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,18 @@ contract FeeSharingCollector is

event RBTCWithdrawn(address indexed sender, address indexed receiver, uint256 amount);

event SetWrbtcToken(
address indexed sender,
address indexed oldWrbtcToken,
address indexed newWrbtcToken
);

event SetLoanTokenWrbtc(
address indexed sender,
address indexed oldLoanTokenWrbtc,
address indexed newLoanTokenWrbtc
);

/* Modifier */
modifier oneTimeExecution(bytes4 _funcSig) {
require(
Expand All @@ -119,6 +131,40 @@ contract FeeSharingCollector is
/// @dev fallback function to support rbtc transfer when unwrap the wrbtc.
function() external payable {}

/**
* @dev initialize function for fee sharing collector proxy
* @param wrbtcToken wrbtc token address
* @param loanWrbtcToken address of loan token wrbtc (IWrbtc)
*/
function initialize(address wrbtcToken, address loanWrbtcToken) external onlyOwner {
tjcloa marked this conversation as resolved.
Show resolved Hide resolved
setWrbtcToken(wrbtcToken);
setLoanTokenWrbtc(loanWrbtcToken);
}

/**
* @notice Set the wrbtc token address of fee sharing collector.
*
* only owner can perform this action.
*
* @param newWrbtcTokenAddress The new address of the wrbtc token.
* */
function setWrbtcToken(address newWrbtcTokenAddress) public onlyOwner {
emit SetWrbtcToken(msg.sender, wrbtcTokenAddress, newWrbtcTokenAddress);
wrbtcTokenAddress = newWrbtcTokenAddress;
tjcloa marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @notice Set the loan wrbtc token address of fee sharing collector.
*
* only owner can perform this action.
*
* @param newLoanTokenWrbtcAddress The new address of the loan wrbtc token.
* */
function setLoanTokenWrbtc(address newLoanTokenWrbtcAddress) public onlyOwner {
emit SetLoanTokenWrbtc(msg.sender, loanTokenWrbtcAddress, newLoanTokenWrbtcAddress);
loanTokenWrbtcAddress = newLoanTokenWrbtcAddress;
tjcloa marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @notice Withdraw fees for the given token:
* lendingFee + tradingFee + borrowingFee
Expand All @@ -137,11 +183,11 @@ contract FeeSharingCollector is

uint256 wrbtcAmountWithdrawn = protocol.withdrawFees(_tokens, address(this));

IWrbtcERC20 wRBTCToken = protocol.wrbtcToken();
IWrbtcERC20 wrbtcToken = IWrbtcERC20(wrbtcTokenAddress);

if (wrbtcAmountWithdrawn > 0) {
// unwrap the wrbtc to rbtc, and hold the rbtc.
wRBTCToken.withdraw(wrbtcAmountWithdrawn);
wrbtcToken.withdraw(wrbtcAmountWithdrawn);

/// @notice Update unprocessed amount of tokens
uint96 amount96 =
Expand All @@ -168,7 +214,7 @@ contract FeeSharingCollector is
* @param _converters array addresses of the converters
* */
function withdrawFeesAMM(address[] memory _converters) public {
IWrbtcERC20 wRBTCToken = protocol.wrbtcToken();
IWrbtcERC20 wrbtcToken = IWrbtcERC20(wrbtcTokenAddress);

// Validate
_validateWhitelistedConverter(_converters);
Expand All @@ -180,7 +226,7 @@ contract FeeSharingCollector is

if (wrbtcAmountWithdrawn > 0) {
// unwrap wrbtc to rbtc, and hold the rbtc
wRBTCToken.withdraw(wrbtcAmountWithdrawn);
wrbtcToken.withdraw(wrbtcAmountWithdrawn);

/// @notice Update unprocessed amount of tokens
uint96 amount96 =
Expand Down Expand Up @@ -220,7 +266,7 @@ contract FeeSharingCollector is
require(success, "Staking::transferTokens: token transfer failed");

// if _token is wrbtc, need to unwrap it to rbtc
IWrbtcERC20 wrbtcToken = protocol.wrbtcToken();
IWrbtcERC20 wrbtcToken = IWrbtcERC20(wrbtcTokenAddress);
if (_token == address(wrbtcToken)) {
wrbtcToken.withdraw(_amount);
_token = RBTC_DUMMY_ADDRESS_FOR_CHECKPOINT;
Expand Down Expand Up @@ -284,9 +330,6 @@ contract FeeSharingCollector is
"FeeSharingCollector::withdraw: _maxCheckpoints should be positive"
);

address wRBTCAddress = address(protocol.wrbtcToken());
address loanPoolTokenWRBTC = _getAndValidateLoanPoolWRBTC(wRBTCAddress);

address user = msg.sender;
if (_receiver == ZERO_ADDRESS) {
_receiver = msg.sender;
Expand All @@ -306,7 +349,7 @@ contract FeeSharingCollector is
}

processedCheckpoints[user][_token] = end;
if (loanPoolTokenWRBTC == _token) {
if (loanTokenWrbtcAddress == _token) {
// We will change, so that feeSharingCollector will directly burn then loanToken (IWRBTC) to rbtc and send to the user --- by call burnToBTC function
ILoanTokenWRBTC(_token).burnToBTC(_receiver, amount, false);
} else {
Expand Down Expand Up @@ -391,16 +434,12 @@ contract FeeSharingCollector is
}

function validRBTCBasedTokens(address[] memory _tokens) private view {
IWrbtcERC20 wrbtcToken = protocol.wrbtcToken();

address loanPoolTokenWRBTC = _getAndValidateLoanPoolWRBTC(address(wrbtcToken));

for (uint256 i = 0; i < _tokens.length; i++) {
address _token = _tokens[i];
if (
_token != RBTC_DUMMY_ADDRESS_FOR_CHECKPOINT &&
_token != address(wrbtcToken) &&
_token != loanPoolTokenWRBTC
_token != wrbtcTokenAddress &&
_token != loanTokenWrbtcAddress
) {
revert("only rbtc-based tokens are allowed");
}
Expand Down Expand Up @@ -437,9 +476,6 @@ contract FeeSharingCollector is
_receiver = msg.sender;
}

IWrbtcERC20 wrbtcToken = protocol.wrbtcToken();
address loanPoolTokenWRBTC = _getAndValidateLoanPoolWRBTC(address(wrbtcToken));

uint256 rbtcAmountToSend;

for (uint256 i = 0; i < _tokens.length; i++) {
Expand All @@ -456,8 +492,8 @@ contract FeeSharingCollector is
: previousProcessedUserCheckpoints;

if (
tokenData.tokenAddress == address(wrbtcToken) ||
tokenData.tokenAddress == loanPoolTokenWRBTC ||
tokenData.tokenAddress == wrbtcTokenAddress ||
tokenData.tokenAddress == loanTokenWrbtcAddress ||
tokenData.tokenAddress == RBTC_DUMMY_ADDRESS_FOR_CHECKPOINT
) {
(totalAmount, endToken) = _withdrawRbtcTokenStartingFromCheckpoint(
Expand Down Expand Up @@ -583,9 +619,7 @@ contract FeeSharingCollector is
{
address user = msg.sender;

IWrbtcERC20 wrbtcToken = protocol.wrbtcToken();

address loanPoolTokenWRBTC = _getAndValidateLoanPoolWRBTC(address(wrbtcToken));
IWrbtcERC20 wrbtcToken = IWrbtcERC20(wrbtcTokenAddress);

(totalAmount, endTokenCheckpoint) = _getRBTCBalance(_token, user, _maxCheckpoints);

Expand All @@ -594,10 +628,10 @@ contract FeeSharingCollector is
if (_token == address(wrbtcToken)) {
// unwrap the wrbtc
wrbtcToken.withdraw(totalAmount);
} else if (_token == loanPoolTokenWRBTC) {
} else if (_token == loanTokenWrbtcAddress) {
// pull out the iWRBTC to rbtc to this feeSharingCollector contract
/** @dev will use the burned result from IWRBTC to RBTC as return total amount */
totalAmount = ILoanTokenWRBTC(loanPoolTokenWRBTC).burnToBTC(
totalAmount = ILoanTokenWRBTC(loanTokenWrbtcAddress).burnToBTC(
address(this),
totalAmount,
false
Expand Down Expand Up @@ -1055,12 +1089,12 @@ contract FeeSharingCollector is
}

function withdrawWRBTC(address receiver, uint256 wrbtcAmount) external onlyOwner {
address wRBTCAddress = address(protocol.wrbtcToken());
IERC20 wrbtcToken = IERC20(wrbtcTokenAddress);

uint256 balance = IERC20(wRBTCAddress).balanceOf(address(this));
uint256 balance = wrbtcToken.balanceOf(address(this));
require(wrbtcAmount <= balance, "Insufficient balance");

IERC20(wRBTCAddress).safeTransfer(receiver, wrbtcAmount);
wrbtcToken.safeTransfer(receiver, wrbtcAmount);
}

/**
Expand Down Expand Up @@ -1110,10 +1144,8 @@ contract FeeSharingCollector is
function getAccumulatedRBTCFeeBalances(address _user) external view returns (uint256) {
(uint256 _rbtcAmount, uint256 _wrbtcAmount, uint256 _iWrbtcAmount, , , ) =
_getRBTCBalances(_user, 0);
IWrbtcERC20 wrbtcToken = protocol.wrbtcToken();
address loanPoolTokenWRBTC = _getAndValidateLoanPoolWRBTC(address(wrbtcToken));
uint256 iWRBTCAmountInRBTC =
_iWrbtcAmount.mul(ILoanTokenWRBTC(loanPoolTokenWRBTC).tokenPrice()).div(1e18);
_iWrbtcAmount.mul(ILoanTokenWRBTC(loanTokenWrbtcAddress).tokenPrice()).div(1e18);
return _rbtcAmount.add(_wrbtcAmount).add(iWRBTCAmountInRBTC);
}

Expand Down Expand Up @@ -1142,10 +1174,6 @@ contract FeeSharingCollector is
uint256 _endIWRBTC
)
{
IWrbtcERC20 wrbtcToken = protocol.wrbtcToken();

address loanPoolTokenWRBTC = _getAndValidateLoanPoolWRBTC(address(wrbtcToken));

(_rbtcAmount, _endRBTC) = _getAccumulatedFees({
_user: _user,
_token: RBTC_DUMMY_ADDRESS_FOR_CHECKPOINT,
Expand All @@ -1155,13 +1183,13 @@ contract FeeSharingCollector is

(_wrbtcAmount, _endWRBTC) = _getAccumulatedFees({
_user: _user,
_token: address(wrbtcToken),
_token: wrbtcTokenAddress,
_startFrom: 0,
_maxCheckpoints: _maxCheckpoints
});
(_iWrbtcAmount, _endIWRBTC) = _getAccumulatedFees({
_user: _user,
_token: loanPoolTokenWRBTC,
_token: loanTokenWrbtcAddress,
_startFrom: 0,
_maxCheckpoints: _maxCheckpoints
});
Expand All @@ -1182,14 +1210,10 @@ contract FeeSharingCollector is
address _user,
uint32 _maxCheckpoints
) internal view returns (uint256 _tokenAmount, uint256 _endToken) {
IWrbtcERC20 wrbtcToken = protocol.wrbtcToken();

address loanPoolTokenWRBTC = _getAndValidateLoanPoolWRBTC(address(wrbtcToken));

if (
_token == RBTC_DUMMY_ADDRESS_FOR_CHECKPOINT ||
_token == address(wrbtcToken) ||
_token == loanPoolTokenWRBTC
_token == wrbtcTokenAddress ||
_token == loanTokenWrbtcAddress
) {
(_tokenAmount, _endToken) = _getAccumulatedFees({
_user: _user,
Expand All @@ -1202,24 +1226,6 @@ contract FeeSharingCollector is
}
}

/**
* @dev private function to get and validate the wrbtc loan pool token address based on the wrbtc token address.
* @dev will revert if wrbtc loan pool token does not exist (zero address)
*
* @param _wRBTCAddress wrbtc token address.
*
* @return wrbtc loan pool wrbtc token address
*/
function _getAndValidateLoanPoolWRBTC(address _wRBTCAddress) internal view returns (address) {
address loanPoolTokenWRBTC = protocol.underlyingToLoanPool(_wRBTCAddress);
require(
loanPoolTokenWRBTC != ZERO_ADDRESS,
"FeeSharingCollector::withdraw: loan wRBTC not found"
);

return loanPoolTokenWRBTC;
}

// @todo update dependency `numTokenCheckpoints` -> `totalTokenCheckpoints` and deprecate numTokenCheckpoints function
/**
* @dev This getter function `numTokenCheckpoints` is added for backwards compatibility
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ contract FeeSharingCollectorStorage is Ownable {

mapping(bytes4 => bool) public isFunctionExecuted;

/**
* @dev Wrbtc token adress
*/
address public wrbtcTokenAddress;

/**
* @dev IWrbtc token adress
tjcloa marked this conversation as resolved.
Show resolved Hide resolved
*/
address public loanTokenWrbtcAddress;

/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* If you mark a function `nonReentrant`, you should also
Expand Down
4 changes: 0 additions & 4 deletions contracts/mockup/FeeSharingCollectorMockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,6 @@ contract FeeSharingCollectorMockup is FeeSharingCollector {
(amount, end) = _getAccumulatedFees(_user, _token, 0, _maxCheckpoints);
}

function invalidLoanPoolWRBTC() public view returns (address) {
return _getAndValidateLoanPoolWRBTC(address(0));
}

function endOfRangeWithZeroMaxCheckpoint(address _token) public view returns (uint256) {
return _getEndOfRange(0, _token, 0);
}
Expand Down
Loading