Skip to content

Gateway staking fee #379

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

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
],
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
},
"solidity.compileUsingRemoteVersion": "v0.8.9+commit.e5eed63a"
}
14 changes: 14 additions & 0 deletions contracts/interface/ILockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ interface ILockup {
external
returns (uint256);

function depositToProperty(
address _property,
uint256 _amount,
address _gatewayAddress,
uint256 _gatewayFee
) external returns (uint256);

function depositToPosition(uint256 _tokenId, uint256 _amount)
external
returns (bool);
Expand All @@ -46,6 +53,13 @@ interface ILockup {

function update() external;

function withdrawByPosition(
uint256 _tokenId,
uint256 _amount,
address _gatewayAddress,
uint256 _gatewayBasisFee
) external returns (bool);

function withdrawByPosition(uint256 _tokenId, uint256 _amount)
external
returns (bool);
Expand Down
173 changes: 142 additions & 31 deletions contracts/src/lockup/Lockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,21 +99,12 @@ contract Lockup is ILockup, InitializableUsingRegistry {
}

/**
* @dev deposit dev token to dev protocol and generate s-token
* @param _property target property address
* @param _amount staking value
* @return tokenId The ID of the created new staking position
*
*/
function depositToProperty(address _property, uint256 _amount)
external
override
onlyAuthenticatedProperty(_property)
function _depositToProperty(address _property, uint256 _amount)
private
returns (uint256)
{
/**
* Validates _amount is not 0.
*/
require(_amount != 0, "illegal deposit amount");
/**
* Gets the latest cumulative sum of the interest price.
*/
Expand Down Expand Up @@ -163,6 +154,63 @@ contract Lockup is ILockup, InitializableUsingRegistry {
return tokenId;
}

/**
* @dev overloaded depositToProperty with gateway fee params
* @param _property target property address
* @param _amount staking value
* @param _gatewayAddress is the address to which the liquidity provider fee will be directed
* @param _gatewayFee is the basis points to pass. For example 10000 is 100%
* @return tokenId The ID of the created new staking position
*/
function depositToProperty(
address _property,
uint256 _amount,
address _gatewayAddress,
uint256 _gatewayFee
) external override onlyAuthenticatedProperty(_property) returns (uint256) {
/**
* Validates _amount is not 0.
*/
require(_amount != 0, "illegal deposit amount");
require(_gatewayFee <= 10000, "must be below 10000");

uint256 feeAmount = (_amount * _gatewayFee) / 10000;

/**
* transfer feeAmount to _gatewayAddress
*/
require(
IERC20(registry().registries("Dev")).transferFrom(
msg.sender,
_gatewayAddress,
feeAmount
),
"dev transfer failed"
);

return _depositToProperty(_property, _amount - feeAmount);
}

/**
* @dev deposit dev token to dev protocol and generate s-token
* @param _property target property address
* @param _amount staking value
* @return tokenId The ID of the created new staking position
*/
function depositToProperty(address _property, uint256 _amount)
external
override
onlyAuthenticatedProperty(_property)
returns (uint256)
{
/**
* Validates _amount is not 0.
*/
require(_amount != 0, "illegal deposit amount");

return _depositToProperty(_property, _amount);
}

/**
* @dev deposit dev token to dev protocol and update s-token status
* @param _tokenId s-token id
Expand Down Expand Up @@ -228,15 +276,20 @@ contract Lockup is ILockup, InitializableUsingRegistry {
}

/**
* Withdraw staking.(NFT)
* @dev Withdraw staking.(NFT)
* Releases staking, withdraw rewards, and transfer the staked and withdraw rewards amount to the sender.
* @param _tokenId s-token id
* @param _amount staking value
* @param _gatewayAddress optional gateway fee address - set address(0) for no fee
* @param _gatewayBasisFee is the basis points fee. For example 10000 is a 100% fee
* @return bool On success, true will be returned
*/
function withdrawByPosition(uint256 _tokenId, uint256 _amount)
external
override
onlyPositionOwner(_tokenId)
returns (bool)
{
function _withdrawByPosition(
uint256 _tokenId,
uint256 _amount,
address _gatewayAddress,
uint256 _gatewayBasisFee
) private returns (bool) {
ISTokensManager sTokenManager = ISTokensManager(
registry().registries("STokensManager")
);
Expand All @@ -253,7 +306,9 @@ contract Lockup is ILockup, InitializableUsingRegistry {
* Withdraws the staking reward
*/
(uint256 value, RewardPrices memory prices) = _withdrawInterest(
positions
positions,
_gatewayAddress,
_gatewayBasisFee
);
/**
* Transfer the staked amount to the sender.
Expand All @@ -265,7 +320,6 @@ contract Lockup is ILockup, InitializableUsingRegistry {
* Saves variables that should change due to the canceling staking..
*/
updateValues(false, positions.property, _amount, prices);
uint256 cumulative = positions.cumulativeReward + value;

/**
* update position information
Expand All @@ -274,7 +328,7 @@ contract Lockup is ILockup, InitializableUsingRegistry {
_tokenId,
positions.amount - _amount,
prices.interest,
cumulative,
positions.cumulativeReward + value,
0
);
if (totalLockedForProperty[positions.property] == 0) {
Expand All @@ -288,6 +342,45 @@ contract Lockup is ILockup, InitializableUsingRegistry {
return result;
}

/**
* @dev Withdraw staking.(NFT)
* Releases staking, withdraw rewards, and transfer the staked and withdraw rewards amount to the sender.
* @param _tokenId s-token id
* @param _amount staking value
* @return bool On success, true will be returned
*/
function withdrawByPosition(uint256 _tokenId, uint256 _amount)
external
override
onlyPositionOwner(_tokenId)
returns (bool)
{
return _withdrawByPosition(_tokenId, _amount, address(0), 0);
}

/**
* @dev withdrawByPosition overloaded with _gatewayAddress and _gatewayBasisFee
* @param _tokenId s-token id
* @param _amount staking value
* @param _gatewayAddress optional gateway fee address - set address(0) for no fee
* @param _gatewayBasisFee is the basis points fee. For example 10000 is a 100% fee
* @return bool On success, true will be returned
*/
function withdrawByPosition(
uint256 _tokenId,
uint256 _amount,
address _gatewayAddress,
uint256 _gatewayBasisFee
) external override onlyPositionOwner(_tokenId) returns (bool) {
return
_withdrawByPosition(
_tokenId,
_amount,
_gatewayAddress,
_gatewayBasisFee
);
}

/**
* get lockup info
*/
Expand Down Expand Up @@ -658,7 +751,9 @@ contract Lockup is ILockup, InitializableUsingRegistry {
* Withdraws staking reward as an interest.
*/
function _withdrawInterest(
ISTokensManager.StakingPositions memory positions
ISTokensManager.StakingPositions memory positions,
address _gatewayAddress,
uint256 _gatewayBasisFee
) private returns (uint256 value_, RewardPrices memory prices_) {
/**
* Gets the withdrawable amount.
Expand All @@ -668,16 +763,32 @@ contract Lockup is ILockup, InitializableUsingRegistry {
RewardPrices memory prices
) = _calculateWithdrawableInterestAmount(positions);

IDevBridge devBridge = IDevBridge(registry().registries("DevBridge"));

/**
* Mints the reward.
* Gateway Fee exists
* send fee to gateway address and the remainder to msg.sender
*/
require(
IDevBridge(registry().registries("DevBridge")).mint(
msg.sender,
value
),
"dev mint failed"
);
if (_gatewayAddress != address(0) && _gatewayBasisFee > 0) {
uint256 feeValue = (value * _gatewayBasisFee) / 10000;

require(
devBridge.mint(msg.sender, value - feeValue),
"dev mint failed"
);

require(
devBridge.mint(_gatewayAddress, feeValue),
"fee dev mint failed"
);
}
/**
* No gateway fee
* send the entirety to msg.sender
*/
else {
require(devBridge.mint(msg.sender, value), "dev mint failed");
}

/**
* Since the total supply of tokens has changed, updates the latest maximum mint amount.
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@devprotocol/protocol-v2",
"version": "0.5.0",
"version": "0.5.1",
"description": "Securitize for Internet assets",
"scripts": {
"test": "truffle test --config truffle-config.js",
Expand Down Expand Up @@ -42,6 +42,7 @@
"eslint-config-xo": "0.41.0",
"eslint-config-xo-typescript": "0.51.1",
"husky": "7.0.4",
"js-base64": "3.7.2",
"p-queue": "7.2.0",
"prettier": "2.7.1",
"prettier-plugin-solidity": "1.0.0-beta.19",
Expand Down
9 changes: 8 additions & 1 deletion test/lockup/lockup-s-token-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,14 @@ export const init2 = async (
): Promise<[DevProtocolInstance, PropertyInstance, number]> => {
const [dev, property] = await init(deployer, user)
await dev.dev.approve(dev.lockup.address, 600)
await dev.lockup.depositToProperty(property.address, 100)

// @ts-expect-error overloading functions aren't working
// pulled from https://github.com/trufflesuite/truffle/issues/3506
await dev.lockup.methods['depositToProperty(address,uint256)'](
property.address,
100
)

const tokenIds = await dev.sTokensManager.positionsOfOwner(deployer)

return [dev, property, tokenIds[0].toNumber()]
Expand Down
Loading