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

feat: atomic ntoken #326

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 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
35 changes: 35 additions & 0 deletions contracts/interfaces/IAtomicCollateralizableERC721.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: AGPL-3.0
pragma solidity 0.8.10;

/**
* @title IAtomicCollateralizableERC721
* @author Parallel
* @notice Defines the basic interface for an CollateralizableERC721.
GopherJ marked this conversation as resolved.
Show resolved Hide resolved
**/
interface IAtomicCollateralizableERC721 {
/**
* @dev get the collateralized atomic token balance of a specific user
*/
function atomicCollateralizedBalanceOf(address user)
external
view
returns (uint256);

/**
* @dev get the atomic token balance of a specific user
*/
function atomicBalanceOf(address user) external view returns (uint256);

/**
* @dev check if specific token is atomic (has multiplier)
*/
function isAtomicToken(uint256 tokenId) external view returns (bool);

/**
* @dev get the trait multiplier of specific token
*/
function getTraitMultiplier(uint256 tokenId)
external
view
returns (uint256);
}
2 changes: 0 additions & 2 deletions contracts/interfaces/INToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,4 @@ interface INToken is
address airdropContract,
bytes calldata airdropParams
) external;

function getAtomicPricingConfig() external view returns (bool);
}
2 changes: 1 addition & 1 deletion contracts/mocks/upgradeability/MockNToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {IPool} from "../../interfaces/IPool.sol";
import {IRewardController} from "../../interfaces/IRewardController.sol";

contract MockNToken is NToken {
constructor(IPool pool) NToken(pool, false) {}
constructor(IPool pool) NToken(pool) {}

function getRevision() internal pure override returns (uint256) {
return 999;
Expand Down
45 changes: 38 additions & 7 deletions contracts/protocol/libraries/logic/GenericLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {Math} from "../../../dependencies/openzeppelin/contracts/Math.sol";
import {IScaledBalanceToken} from "../../../interfaces/IScaledBalanceToken.sol";
import {INToken} from "../../../interfaces/INToken.sol";
import {ICollateralizableERC721} from "../../../interfaces/ICollateralizableERC721.sol";
import {IAtomicCollateralizableERC721} from "../../../interfaces/IAtomicCollateralizableERC721.sol";
import {IPriceOracleGetter} from "../../../interfaces/IPriceOracleGetter.sol";
import {ReserveConfiguration} from "../configuration/ReserveConfiguration.sol";
import {UserConfiguration} from "../configuration/UserConfiguration.sol";
Expand All @@ -15,7 +16,7 @@ import {WadRayMath} from "../math/WadRayMath.sol";
import {DataTypes} from "../types/DataTypes.sol";
import {ReserveLogic} from "./ReserveLogic.sol";
import {INonfungiblePositionManager} from "../../../dependencies/uniswap/INonfungiblePositionManager.sol";
import {XTokenType} from "../../../interfaces/IXTokenType.sol";
import {XTokenType, IXTokenType} from "../../../interfaces/IXTokenType.sol";

/**
* @title GenericLogic library
Expand Down Expand Up @@ -364,11 +365,13 @@ library GenericLogic {
CalculateUserAccountDataVars memory vars
) private view returns (uint256 totalValue) {
INToken nToken = INToken(vars.xTokenAddress);
bool isAtomicPrice = nToken.getAtomicPricingConfig();
if (isAtomicPrice) {
uint256 totalBalance = nToken.balanceOf(params.user);
uint256 balance = INToken(vars.xTokenAddress).balanceOf(params.user);

for (uint256 index = 0; index < totalBalance; index++) {
if (
IXTokenType(vars.xTokenAddress).getXTokenType() ==
XTokenType.NTokenUniswapV3
) {
for (uint256 index = 0; index < balance; index++) {
uint256 tokenId = nToken.tokenOfOwnerByIndex(
params.user,
index
Expand All @@ -385,14 +388,42 @@ library GenericLogic {
}
}
} else {
uint256 collateralizedBalance = ICollateralizableERC721(
vars.xTokenAddress
).collateralizedBalanceOf(params.user);
uint256 atomicCollateralizedBalance = IAtomicCollateralizableERC721(
vars.xTokenAddress
GopherJ marked this conversation as resolved.
Show resolved Hide resolved
).atomicCollateralizedBalanceOf(params.user);
uint256 atomicBalance = IAtomicCollateralizableERC721(
vars.xTokenAddress
).atomicBalanceOf(params.user);
uint256 assetPrice = _getAssetPrice(
params.oracle,
vars.currentReserveAddress
);
totalValue =
ICollateralizableERC721(vars.xTokenAddress)
.collateralizedBalanceOf(params.user) *
(collateralizedBalance - atomicCollateralizedBalance) *
assetPrice;

for (
uint256 index = balance - atomicBalance;
GopherJ marked this conversation as resolved.
Show resolved Hide resolved
index < balance;
index++
) {
uint256 tokenId = nToken.tokenOfOwnerByIndex(
params.user,
index
);
if (
ICollateralizableERC721(vars.xTokenAddress)
.isUsedAsCollateral(tokenId)
) {
uint256 multiplier = IAtomicCollateralizableERC721(
vars.xTokenAddress
).getTraitMultiplier(tokenId);
totalValue += assetPrice.wadMul(multiplier);
}
}
}
}

Expand Down
18 changes: 17 additions & 1 deletion contracts/protocol/libraries/logic/LiquidationLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import {Address} from "../../../dependencies/openzeppelin/contracts/Address.sol"
import {IPToken} from "../../../interfaces/IPToken.sol";
import {IWETH} from "../../../misc/interfaces/IWETH.sol";
import {ICollateralizableERC721} from "../../../interfaces/ICollateralizableERC721.sol";
import {IAtomicCollateralizableERC721} from "../../../interfaces/IAtomicCollateralizableERC721.sol";
import {IAuctionableERC721} from "../../../interfaces/IAuctionableERC721.sol";
import {IXTokenType, XTokenType} from "../../../interfaces/IXTokenType.sol";
import {INToken} from "../../../interfaces/INToken.sol";
import {PRBMath} from "../../../dependencies/math/PRBMath.sol";
import {PRBMathUD60x18} from "../../../dependencies/math/PRBMathUD60x18.sol";
Expand All @@ -40,6 +42,7 @@ library LiquidationLogic {
using UserConfiguration for DataTypes.UserConfigurationMap;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
using PRBMathUD60x18 for uint256;
using WadRayMath for uint256;
using GPv2SafeERC20 for IERC20;

/**
Expand Down Expand Up @@ -776,12 +779,25 @@ library LiquidationLogic {
).collateralizedBalanceOf(params.borrower);

// price of the asset that is used as collateral
if (INToken(superVars.collateralXToken).getAtomicPricingConfig()) {
if (
IXTokenType(superVars.collateralXToken).getXTokenType() ==
GopherJ marked this conversation as resolved.
Show resolved Hide resolved
XTokenType.NTokenUniswapV3
) {
vars.collateralPrice = IPriceOracleGetter(params.priceOracle)
.getTokenPrice(
params.collateralAsset,
params.collateralTokenId
);
} else if (
IAtomicCollateralizableERC721(superVars.collateralXToken)
GopherJ marked this conversation as resolved.
Show resolved Hide resolved
.isAtomicToken(params.collateralTokenId)
) {
uint256 multiplier = IAtomicCollateralizableERC721(
superVars.collateralXToken
).getTraitMultiplier(params.collateralTokenId);
vars.collateralPrice = IPriceOracleGetter(params.priceOracle)
.getAssetPrice(params.collateralAsset)
.wadMul(multiplier);
} else {
vars.collateralPrice = IPriceOracleGetter(params.priceOracle)
.getAssetPrice(params.collateralAsset);
Expand Down
13 changes: 2 additions & 11 deletions contracts/protocol/tokenization/NToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,8 @@ contract NToken is VersionedInitializable, MintableIncentivizedERC721, INToken {
* @dev Constructor.
* @param pool The address of the Pool contract
*/
constructor(IPool pool, bool atomic_pricing)
MintableIncentivizedERC721(
pool,
"NTOKEN_IMPL",
"NTOKEN_IMPL",
atomic_pricing
)
constructor(IPool pool)
MintableIncentivizedERC721(pool, "NTOKEN_IMPL", "NTOKEN_IMPL")
{}

function initialize(
Expand Down Expand Up @@ -321,10 +316,6 @@ contract NToken is VersionedInitializable, MintableIncentivizedERC721, INToken {
return IERC721Metadata(_underlyingAsset).tokenURI(tokenId);
}

function getAtomicPricingConfig() external view returns (bool) {
return ATOMIC_PRICING;
}

function getXTokenType()
external
pure
Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/tokenization/NTokenApeStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ abstract contract NTokenApeStaking is NToken, INTokenApeStaking {
* @dev Constructor.
* @param pool The address of the Pool contract
*/
constructor(IPool pool, address apeCoinStaking) NToken(pool, false) {
constructor(IPool pool, address apeCoinStaking) NToken(pool) {
_apeCoinStaking = ApeCoinStaking(apeCoinStaking);
}

Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/tokenization/NTokenBAKC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ contract NTokenBAKC is NToken {
address apeCoinStaking,
address _nBAYC,
address _nMAYC
) NToken(pool, false) {
) NToken(pool) {
_apeCoinStaking = ApeCoinStaking(apeCoinStaking);
nBAYC = _nBAYC;
nMAYC = _nMAYC;
Expand Down
2 changes: 1 addition & 1 deletion contracts/protocol/tokenization/NTokenMoonBirds.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ contract NTokenMoonBirds is NToken, IMoonBirdBase {
* @dev Constructor.
* @param pool The address of the Pool contract
*/
constructor(IPool pool) NToken(pool, false) {
constructor(IPool pool) NToken(pool) {
// Intentionally left blank
}

Expand Down
11 changes: 10 additions & 1 deletion contracts/protocol/tokenization/NTokenUniswapV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ contract NTokenUniswapV3 is NToken, INTokenUniswapV3 {
* @dev Constructor.
* @param pool The address of the Pool contract
*/
constructor(IPool pool) NToken(pool, true) {
constructor(IPool pool) NToken(pool) {
_ERC721Data.balanceLimit = 30;
}

Expand Down Expand Up @@ -141,6 +141,15 @@ contract NTokenUniswapV3 is NToken, INTokenUniswapV3 {
);
}

function setTraitsMultipliers(uint256[] calldata, uint256[] calldata)
external
override
onlyPoolAdmin
nonReentrant
{
revert();
}

function _safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "ETH_TRANSFER_FAILED");
Expand Down
Loading