Skip to content

Commit

Permalink
feat: add getSubtotal (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xashu authored May 21, 2024
1 parent e763dbd commit d8a7214
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 169 deletions.
83 changes: 53 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
<pre align="center">
<em></em>
<img src="images/banner.png" width="300">
<em></em>
<em>A NEW WAY TO PAY.</em>
<em>Payment via the bonding curve and yield farming.</em>
<em></em>
</pre>

Mest, **a payment protocol designed for creators**. And it's a bridge between creators and fans, where fans can **donate, sponsor, subscribe**, etc. The contract provides a new way to pay where you can stake ETH by a **sigmoid bonding curve** and **yield farming**, buy what you need, and withdraw whenever you want.

- 🐦 For fans, pay early and save more;
- 💵 For creators, long-term income from fees and yield;
- ⚡ Lightweight with flexible curve and yield strategies;
- 🌟 Made for creators like startups, indie hackers and KOLs.
<samp>
<sub><em>Value4Value</em></sub>

<div align="center">

| Features | Mest | FriendtechV1 | Patreon | Coinbase Commerce |
| ------------------ | ----- | ------------ | ------- | ----------------- |
| User Capacity | > 10K | < 100 | N/A | N/A |
| Capital efficiency |||||
| Permissionless |||||
| Tokenization |||||
<div align="center">
<br />
<em>A NEW WAY TO PAY.</em> <br />
<em>Payment via the bonding curve and yield farming.</em>
<br />
</div>
</samp>

##

**A payment protocol designed for creators**, it bridges the gap between creators and fans, where fans can **donate, sponsor, subscribe**, and more, while creators receive **fees and yield**.

- For fans, pay early and earn more;
- For creators, long-term income from fees and yield;
- Lightweight with flexible curve and yield strategies;
- No protocol fee, any client can be charged via referral fee;
- Stake what you need, and withdraw when you want;
- Made for creators like startups, indie hackers and KOLs.

</div>

## How it works?

The contract uses a sigmoid bonding curve for dynamic pricing. When you buy, it mints tokens and drives prices up, then when you sell, it burns tokens and drives prices down. The staked ETH is allocated in an interest-rate market to generate sustainable rewards, which are then redistributed to the creators.
Expand All @@ -33,19 +28,47 @@ The contract uses a sigmoid bonding curve for dynamic pricing. When you buy, it
<img src="images/curve.gif" width="80%">
</div>

## Contracts
## Why it is better?
<div align="center">

| Features | V4V | Friendtech | Patreon | Coinbase Commerce |
|--------------------|-------|------------|---------|-------------------|
| Flexible strategy | ★★★★★ | ★★★☆☆ | ★★★☆☆ | ★☆☆☆☆ |
| Capital efficiency | ★★★☆☆ | ★☆☆☆☆ | ★☆☆☆☆ | ★☆☆☆☆ |
| Permissionless | ★★★★★ | ★★★★★ | ☆☆☆☆☆ | ★★★☆☆ |
| Tokenization | ★★★★★ | ★★★☆☆ | ☆☆☆☆☆ | ☆☆☆☆☆ |
| Protocol Fee | ★★★★☆ | ★★☆☆☆ | ★☆☆☆☆ | ★★★☆☆ |

</div>

## Smart Contracts

### NFT

The token is a standard ERC1155 contract, with NFTs acting as shares in the bonding curve. When you trade shares, NFTs are minted or burned.
> The token is a standard ERC1155 contract, with NFTs acting as shares in the bonding curve. When you trade shares, NFTs are minted or burned.
| Network | Address |
|------------------|--------------------------------------------|
| Optimism Mainnet | N/A |
| Optimism Sepolia | 0x07cB2490DfBFd63613318F87156D935ddAcb62F4 |

### Shares

SharesFactory is the core contract that contains the bonding curve and yield aggregator logic where you can mint, buy, and sell shares, as well as change yield strategies and claim yields.
> SharesFactory is the core contract that contains the bonding curve and yield aggregator logic where you can mint, buy, and sell shares, as well as change yield strategies and claim yields.
| Network | Address |
|------------------|--------------------------------------------|
| Optimism Mainnet | N/A |
| Optimism Sepolia | 0x5F31921A68eA5b350baF141536933Cc7d70EBAEa |

### Yield

YieldAggregator is a yield strategy contract that provides a common interface for SharesFactory to use, such as deposit, withdraw, and claimable. However, the underlying logic can be any yield strategy, such as Aave, Pendle and LRT, or nothing at all.
> YieldAggregator is a yield strategy contract that provides a common interface for SharesFactory to use, such as deposit, withdraw, and claimable. However, the underlying logic can be any yield strategy, such as Aave, Pendle and LRT, or nothing at all.
| Network | Address |
|------------------|--------------------------------------------|
| Optimism Mainnet | N/A |
| Optimism Sepolia | 0x2c1414c3F442AA7a4E531E2891009Dd1a8744b59 |

## Test and Deploy

Expand All @@ -65,4 +88,4 @@ deploy

## Acknowledgement

Thanks to [Simon de la Rouviere](https://docs.google.com/document/d/1VNkBjjGhcZUV9CyC0ccWYbqeOoVKT2maqX0rK3yXB20), whose ideas inspired Mest to combine curated market with bonding curves, and to the ideal S-curve model from [sound protocol](https://github.com/soundxyz/sound-protocol), we’ve also learned the principle of minimalism from [friend tech](https://www.friend.tech) and [bodhi](https://bodhi.wtf).
Thanks to [Simon de la Rouviere](https://docs.google.com/document/d/1VNkBjjGhcZUV9CyC0ccWYbqeOoVKT2maqX0rK3yXB20), whose ideas inspired *V4V* to combine curated market with bonding curves, and to the ideal S-curve model from [sound protocol](https://github.com/soundxyz/sound-protocol), we’ve also learned the principle of minimalism from [friend tech](https://www.friend.tech) and [bodhi](https://bodhi.wtf).
52 changes: 21 additions & 31 deletions contracts/core/SharesFactoryV1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ contract SharesFactoryV1 is Ownable {
event SetCurve(uint8 indexed curveType);
event SetFee(uint256 indexed feePercent, string feeType);
event Mint(uint256 indexed id, address indexed creator, uint8 indexed curveType);
event Buy(uint256 indexed id, address indexed buyer, uint256 quantity, uint256 totalPrice);
event Sell(uint256 indexed id, address indexed seller, uint256 quantity, uint256 totalPrice);
event Buy(uint256 indexed id, address indexed buyer, uint32 quantity, uint256 totalPrice);
event Sell(uint256 indexed id, address indexed seller, uint32 quantity, uint256 totalPrice);

constructor(
address _ERC1155,
Expand Down Expand Up @@ -73,26 +73,20 @@ contract SharesFactoryV1 is Ownable {
return (share.creator, share.curveType);
}

function getCurve(uint8 curveType)
public
view
returns (
uint96 basePrice,
uint32 inflectionPoint,
uint128 inflectionPrice,
uint128 linearPriceSlope,
bool exists
)
{
function getCurve(uint8 curveType) public view returns (uint96, uint32, uint128, uint128, bool) {
require(curvesMap[curveType].exists, "Invalid curveType");
Curve memory curve = curvesMap[curveType];
return (
curve.basePrice,
curve.inflectionPoint,
curve.inflectionPrice,
curve.linearPriceSlope,
curve.exists
);
uint96 basePrice = curve.basePrice;
uint32 g = curve.inflectionPoint;
uint128 h = curve.inflectionPrice;
uint128 m = curve.linearPriceSlope;
bool exists = curve.exists;
return (basePrice, g, h, m, exists);
}

function getSubTotal(uint32 fromSupply, uint32 quantity, uint8 curveType) public view returns (uint256) {
(uint96 basePrice, uint32 g, uint128 h, uint128 m,) = getCurve(curveType);
return _subTotal(fromSupply, quantity, basePrice, g, h, m);
}

function setReferralFeePercent(uint256 _feePercent) external onlyOwner {
Expand Down Expand Up @@ -305,7 +299,7 @@ contract SharesFactoryV1 is Ownable {
uint256 fromSupply = IShare(ERC1155).shareFromSupply(shareId);
uint256 actualReferralFeePercent = referral != address(0) ? referralFeePercent : 0;

buyPrice = _subTotal(uint32(fromSupply), quantity, curveType);
buyPrice = getSubTotal(uint32(fromSupply), quantity, curveType);
referralFee = (buyPrice * actualReferralFeePercent) / 1 ether;
creatorFee = (buyPrice * creatorFeePercent) / 1 ether;
buyPriceAfterFee = buyPrice + referralFee + creatorFee;
Expand Down Expand Up @@ -337,7 +331,7 @@ contract SharesFactoryV1 is Ownable {
uint256 actualReferralFeePercent = referral != address(0) ? referralFeePercent : 0;
require(fromSupply >= quantity, "Exceeds supply");

sellPrice = _subTotal(uint32(fromSupply) - quantity, quantity, curveType);
sellPrice = getSubTotal(uint32(fromSupply) - quantity, quantity, curveType);
referralFee = (sellPrice * actualReferralFeePercent) / 1 ether;
creatorFee = (sellPrice * creatorFeePercent) / 1 ether;
sellPriceAfterFee = sellPrice - referralFee - creatorFee;
Expand Down Expand Up @@ -380,15 +374,11 @@ contract SharesFactoryV1 is Ownable {
function _subTotal(
uint32 fromSupply,
uint32 quantity,
uint8 curveType
) public view returns (uint256 subTotal) {
(
uint96 basePrice,
uint32 inflectionPoint,
uint128 inflectionPrice,
uint128 linearPriceSlope,
) = getCurve(curveType);

uint96 basePrice,
uint32 inflectionPoint,
uint128 inflectionPrice,
uint128 linearPriceSlope
) public pure returns (uint256 subTotal) {
unchecked {
subTotal = basePrice * quantity;
subTotal += BondingCurveLib.linearSum(linearPriceSlope, fromSupply, quantity);
Expand Down
Binary file removed images/banner.png
Binary file not shown.
Binary file modified images/curve.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 6 additions & 5 deletions test/BaseTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ contract BaseTest is Test {
AaveYieldAggregator public aaveYieldAggregator;
BlankYieldAggregator public blankYieldAggregator;

address public receiver = address(999);
address public owner = address(1);
uint8 public defaultCurveType = 0;
address public owner = makeAddr("owner");
address public addrAlice = makeAddr("addrAlice");
address public addrBob = makeAddr("addrBob");
address public referralReceiver = makeAddr("referralReceiver");
address public yieldReceiver = makeAddr("yieldReceiver");

/**
* @dev Below are the related token/contract addresses on the Optimism mainnet.
Expand Down Expand Up @@ -64,9 +68,6 @@ contract BaseTest is Test {
sharesNFT.transferOwnership(owner);
sharesFactory.transferOwnership(owner);
aaveYieldAggregator.transferOwnership(owner);

// vm.prank(owner);
// sharesFactory.migrate(address(aaveYieldAggregator));
}

function testSuccess() public { }
Expand Down
Loading

0 comments on commit d8a7214

Please sign in to comment.