Skip to content

Commit

Permalink
Refactor: fix bonding curve paramters (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
SocratesLu authored May 20, 2024
1 parent 9472c00 commit e763dbd
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 46 deletions.
58 changes: 29 additions & 29 deletions contracts/core/SharesFactoryV1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
)
{
Expand All @@ -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");

Expand Down Expand Up @@ -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);
}
Expand All @@ -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");

Expand Down Expand Up @@ -245,7 +245,7 @@ contract SharesFactoryV1 is Ownable {
*/
function sellShare(
uint256 shareId,
uint256 quantity,
uint32 quantity,
uint256 minETHAmount,
address referral
) public {
Expand Down Expand Up @@ -289,7 +289,7 @@ contract SharesFactoryV1 is Ownable {
*/
function getBuyPriceAfterFee(
uint256 shareId,
uint256 quantity,
uint32 quantity,
address referral
)
public
Expand All @@ -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;
Expand All @@ -320,7 +320,7 @@ contract SharesFactoryV1 is Ownable {
*/
function getSellPriceAfterFee(
uint256 shareId,
uint256 quantity,
uint32 quantity,
address referral
)
public
Expand All @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down
16 changes: 8 additions & 8 deletions contracts/lib/BondingCurveLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -72,4 +72,4 @@ library BondingCurveLib {
return m * ((n * (n + 1) - k * (k + 1)) >> 1);
}
}
}
}
8 changes: 4 additions & 4 deletions test/BaseTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
15 changes: 11 additions & 4 deletions test/unit/SharesFactory.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -402,35 +402,42 @@ 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) {
assertEq(reason, "Exceeds supply");
}
}

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));
Expand Down
2 changes: 1 addition & 1 deletion test/unit/YieldAggregator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit e763dbd

Please sign in to comment.