diff --git a/contracts/core/SharesFactoryV1.sol b/contracts/core/SharesFactoryV1.sol index 9c28471..db3c954 100644 --- a/contracts/core/SharesFactoryV1.sol +++ b/contracts/core/SharesFactoryV1.sol @@ -13,10 +13,10 @@ contract SharesFactoryV1 is Ownable { using SafeERC20 for IERC20; struct Curve { - uint256 basePrice; - uint256 linearPriceSlope; - uint256 inflectionPoint; - uint256 inflectionPrice; + uint96 basePrice; + uint128 linearPriceSlope; + uint32 inflectionPoint; + uint128 inflectionPrice; bool exists; } @@ -45,10 +45,10 @@ contract SharesFactoryV1 is Ownable { constructor( address _ERC1155, - uint256 _basePrice, - uint256 _inflectionPoint, - uint256 _inflectionPrice, - uint256 _linearPriceSlope + uint96 _basePrice, + uint32 _inflectionPoint, + uint128 _inflectionPrice, + uint128 _linearPriceSlope ) { // Set ERC1155 address ERC1155 = _ERC1155; @@ -77,10 +77,10 @@ contract SharesFactoryV1 is Ownable { public view returns ( - uint256 basePrice, - uint256 inflectionPoint, - uint256 inflectionPrice, - uint256 linearPriceSlope, + uint96 basePrice, + uint32 inflectionPoint, + uint128 inflectionPrice, + uint128 linearPriceSlope, bool exists ) { @@ -107,10 +107,10 @@ contract SharesFactoryV1 is Ownable { function setCurveType( uint8 _curveType, - uint256 _basePrice, - uint256 _inflectionPoint, - uint256 _inflectionPrice, - uint256 _linearPriceSlope + uint96 _basePrice, + uint32 _inflectionPoint, + uint128 _inflectionPrice, + uint128 _linearPriceSlope ) external onlyOwner { require(!curvesMap[_curveType].exists, "Curve already initialized"); @@ -179,7 +179,7 @@ contract SharesFactoryV1 is Ownable { * @param quantity The quantity of shares. * @param referral The address of the referral fee recipient. */ - function mintAndBuyShare(uint8 curveType, uint256 quantity, address referral) public payable { + function mintAndBuyShare(uint8 curveType, uint32 quantity, address referral) public payable { mintShare(curveType); buyShare(shareIndex - 1, quantity, referral); } @@ -204,7 +204,7 @@ contract SharesFactoryV1 is Ownable { * @param quantity The quantity of shares. * @param referral The address of the referral fee recipient. */ - function buyShare(uint256 shareId, uint256 quantity, address referral) public payable { + function buyShare(uint256 shareId, uint32 quantity, address referral) public payable { require(address(yieldAggregator) != address(0), "Invalid yieldAggregator"); require(shareId < shareIndex, "Invalid shareId"); @@ -245,7 +245,7 @@ contract SharesFactoryV1 is Ownable { */ function sellShare( uint256 shareId, - uint256 quantity, + uint32 quantity, uint256 minETHAmount, address referral ) public { @@ -289,7 +289,7 @@ contract SharesFactoryV1 is Ownable { */ function getBuyPriceAfterFee( uint256 shareId, - uint256 quantity, + uint32 quantity, address referral ) public @@ -305,7 +305,7 @@ contract SharesFactoryV1 is Ownable { uint256 fromSupply = IShare(ERC1155).shareFromSupply(shareId); uint256 actualReferralFeePercent = referral != address(0) ? referralFeePercent : 0; - buyPrice = _subTotal(fromSupply, quantity, curveType); + buyPrice = _subTotal(uint32(fromSupply), quantity, curveType); referralFee = (buyPrice * actualReferralFeePercent) / 1 ether; creatorFee = (buyPrice * creatorFeePercent) / 1 ether; buyPriceAfterFee = buyPrice + referralFee + creatorFee; @@ -320,7 +320,7 @@ contract SharesFactoryV1 is Ownable { */ function getSellPriceAfterFee( uint256 shareId, - uint256 quantity, + uint32 quantity, address referral ) public @@ -337,7 +337,7 @@ contract SharesFactoryV1 is Ownable { uint256 actualReferralFeePercent = referral != address(0) ? referralFeePercent : 0; require(fromSupply >= quantity, "Exceeds supply"); - sellPrice = _subTotal(fromSupply - quantity, quantity, curveType); + sellPrice = _subTotal(uint32(fromSupply) - quantity, quantity, curveType); referralFee = (sellPrice * actualReferralFeePercent) / 1 ether; creatorFee = (sellPrice * creatorFeePercent) / 1 ether; sellPriceAfterFee = sellPrice - referralFee - creatorFee; @@ -378,15 +378,15 @@ contract SharesFactoryV1 is Ownable { * @return subTotal The area under the bonding curve. */ function _subTotal( - uint256 fromSupply, - uint256 quantity, + uint32 fromSupply, + uint32 quantity, uint8 curveType ) public view returns (uint256 subTotal) { ( - uint256 basePrice, - uint256 inflectionPoint, - uint256 inflectionPrice, - uint256 linearPriceSlope, + uint96 basePrice, + uint32 inflectionPoint, + uint128 inflectionPrice, + uint128 linearPriceSlope, ) = getCurve(curveType); unchecked { diff --git a/contracts/lib/BondingCurveLib.sol b/contracts/lib/BondingCurveLib.sol index d678f22..25b6127 100644 --- a/contracts/lib/BondingCurveLib.sol +++ b/contracts/lib/BondingCurveLib.sol @@ -6,10 +6,10 @@ import { FixedPointMathLib } from "solady/utils/FixedPointMathLib.sol"; library BondingCurveLib { function sigmoid2Sum( - uint256 inflectionPoint, - uint256 inflectionPrice, - uint256 fromSupply, - uint256 quantity + uint32 inflectionPoint, + uint128 inflectionPrice, + uint32 fromSupply, + uint32 quantity ) internal pure returns (uint256 sum) { // We don't need checked arithmetic for the sum. // The max possible sum for the quadratic region is capped at: @@ -53,9 +53,9 @@ library BondingCurveLib { } function linearSum( - uint256 linearPriceSlope, - uint256 fromSupply, - uint256 quantity + uint128 linearPriceSlope, + uint32 fromSupply, + uint32 quantity ) internal pure returns (uint256 sum) { // We don't need checked arithmetic for the sum because the max possible // intermediate value is capped at: @@ -72,4 +72,4 @@ library BondingCurveLib { return m * ((n * (n + 1) - k * (k + 1)) >> 1); } } -} +} \ No newline at end of file diff --git a/test/BaseTest.t.sol b/test/BaseTest.t.sol index a9058e1..2b3838d 100644 --- a/test/BaseTest.t.sol +++ b/test/BaseTest.t.sol @@ -39,10 +39,10 @@ contract BaseTest is Test { IERC20 public aWETH = IERC20(IAavePool(AAVE_POOL).getReserveData(WETH).aTokenAddress); string public constant BASE_URI = "https://v4v.com/shares/uri/"; - uint256 public constant BASE_PRICE = 5000000000000000; // 0.005 ETH as base price - uint256 public constant INFLECTION_POINT = 1500; - uint256 public constant INFLECTION_PRICE = 102500000000000000; - uint256 public constant LINEAR_PRICE_SLOPE = 0; + uint96 public constant BASE_PRICE = 5000000000000000; // 0.005 ETH as base price + uint32 public constant INFLECTION_POINT = 1500; + uint128 public constant INFLECTION_PRICE = 102500000000000000; + uint128 public constant LINEAR_PRICE_SLOPE = 0; function createFactory() public { sharesNFT = new SharesERC1155(BASE_URI); diff --git a/test/unit/SharesFactory.t.sol b/test/unit/SharesFactory.t.sol index d0f6ddc..1c02baf 100644 --- a/test/unit/SharesFactory.t.sol +++ b/test/unit/SharesFactory.t.sol @@ -402,7 +402,7 @@ contract SharesFactoryTests is BaseTest { } } - function testFuzz_getSellPriceAfterFee(uint256 quantity, address referral) public view { + function testFuzz_getSellPriceAfterFee(uint32 quantity, address referral) public view { try sharesFactory.getSellPriceAfterFee(0, quantity, referral) returns (uint256 price, uint256, uint256, uint256) { assertGe(price, 0); } catch Error(string memory reason) { @@ -410,27 +410,34 @@ contract SharesFactoryTests is BaseTest { } } + function testFuzz_buyShare(uint8 quantity) public { + vm.deal(addrBob, 100 ether); + + _mintAndBuyShare(addrBob, 0, quantity, addrAlice); + test_safeTransferETHWithZero(); + } + /* ******************************************************************************** * Private Tests ******************************************************************************** */ - function _mintAndBuyShare(address sender, uint8 curveType, uint256 quantity, address referral) internal { + function _mintAndBuyShare(address sender, uint8 curveType, uint32 quantity, address referral) internal { uint256 buyPrice = sharesFactory._subTotal(0, quantity, curveType); vm.prank(address(sender)); sharesFactory.mintAndBuyShare{ value: buyPrice * 110 / 100 }(curveType, quantity, referral); } - function _buyShare(address sender, uint256 shareId, uint256 quantity, address referral) internal { + function _buyShare(address sender, uint256 shareId, uint32 quantity, address referral) internal { (uint256 buyPriceAfterFee,,,) = sharesFactory.getBuyPriceAfterFee(shareId, quantity, referral); vm.prank(address(sender)); sharesFactory.buyShare{ value: buyPriceAfterFee }(shareId, quantity, referral); } - function _sellShare(address sender, uint256 shareId, uint256 quantity, address referral) internal { + function _sellShare(address sender, uint256 shareId, uint32 quantity, address referral) internal { (uint256 sellPriceAfterFee,,,) = sharesFactory.getSellPriceAfterFee(shareId, quantity, referral); vm.prank(address(sender)); diff --git a/test/unit/YieldAggregator.t.sol b/test/unit/YieldAggregator.t.sol index da67fdd..3bd9489 100644 --- a/test/unit/YieldAggregator.t.sol +++ b/test/unit/YieldAggregator.t.sol @@ -88,7 +88,7 @@ contract YieldAggregatorTests is BaseTest { assertEq(bobShareBal, 2); } - function _buyShare(address sender, uint256 shareId, uint256 quantity, address referral) internal { + function _buyShare(address sender, uint256 shareId, uint32 quantity, address referral) internal { (uint256 buyPriceAfterFee,,,) = sharesFactory.getBuyPriceAfterFee(shareId, quantity, referral); vm.prank(address(sender)); sharesFactory.buyShare{ value: buyPriceAfterFee }(shareId, quantity, referral);