diff --git a/src/NFTStakingAndBorrowing.sol b/src/NFTStakingAndBorrowing.sol new file mode 100644 index 0000000..da75262 --- /dev/null +++ b/src/NFTStakingAndBorrowing.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.20; + +import {UD60x18, ud} from "@prb/math/src/UD60x18.sol"; + +contract NFTStakingAndBorrowing { + uint256 internal constant YEAR_IN_SECONDS = 31536000; // 365 days + uint256 internal constant DECIMALS_MULTIPLIER = 1e18; + uint256 internal constant BPS = 1e4; + uint256 internal lastUpdateTimestamp; + + uint256 public constant PROTOCOL_YIELD = 1200 * DECIMALS_MULTIPLIER / BPS; + + function calculateDebt(uint256 borrowedAmount, uint256 currentTime, uint256 expirationTime) + public + pure + returns (uint256) + { + UD60x18 timeDelta = ud(expirationTime) - ud(currentTime); + + UD60x18 debtLog2 = (timeDelta / ud(YEAR_IN_SECONDS)) * (ud(DECIMALS_MULTIPLIER) + ud(PROTOCOL_YIELD)).log2() + + ud(borrowedAmount).log2(); + + return debtLog2.exp2().intoUint256(); + } + + function calculateMaxBorrow(uint256 totalAmount, uint256 currentTime, uint256 expirationTime) + public + pure + returns (uint256) + { + UD60x18 timeDelta = ud(expirationTime) - ud(currentTime); + + UD60x18 maxBorrow = ud(totalAmount).log2() + - (timeDelta / ud(YEAR_IN_SECONDS)) * (ud(DECIMALS_MULTIPLIER) + ud(PROTOCOL_YIELD)).log2(); + + return maxBorrow.exp2().intoUint256(); + } +} diff --git a/test/NFTStakingAndBorrowing.t.sol b/test/NFTStakingAndBorrowing.t.sol new file mode 100644 index 0000000..319300f --- /dev/null +++ b/test/NFTStakingAndBorrowing.t.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.20; + +import {Test, console} from "forge-std/Test.sol"; +import {NFTStakingAndBorrowing} from "../src/NFTStakingAndBorrowing.sol"; + +contract NFTStakingAndBorrowingTest is Test { + NFTStakingAndBorrowing public nftStaking; + + function setUp() public { + nftStaking = new NFTStakingAndBorrowing(); + } + + function test_calculateDebt() public view { + uint256 newDebt = nftStaking.calculateDebt(89896e16, 1706745600, 1735689600); + assertEq(newDebt, 997500388704920390522); + } + + function test_calculateMaxBorrow() public view { + uint256 maxBorrow = nftStaking.calculateMaxBorrow(9975e17, 1706745600, 1735689600); + assertEq(maxBorrow, 898959649694196407801); + } + + function testFuzz_MaxBorrow(uint64 x) public view { + uint256 x256 = (uint256(x) + uint256(2)) * 1e18; + uint256 maxBorrow = nftStaking.calculateMaxBorrow(x256, 1706745600, 1735689600); + assertLe(maxBorrow, x256); + } +}