Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
98 changes: 19 additions & 79 deletions src/BondingCurve.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,16 @@
pragma solidity ^0.8.13;

import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol";
import {
SafeERC20
} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {
IUniswapV2Factory
} from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import {
IUniswapV2Pair
} from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import {
IUniswapV2ERC20
} from "@uniswap/v2-core/contracts/interfaces/IUniswapV2ERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IUniswapV2Factory} from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import {IUniswapV2Pair} from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";
import {IUniswapV2ERC20} from "@uniswap/v2-core/contracts/interfaces/IUniswapV2ERC20.sol";

import {IToken} from "./interfaces/IToken.sol";
import {IGNad} from "./interfaces/IGNad.sol";
import {IBondingCurveFactory} from "./interfaces/IBondingCurveFactory.sol";
import {IBondingCurve} from "./interfaces/IBondingCurve.sol";
import * as CustomErrors from "./errors/CustomErrors.sol";
import "./errors/CustomErrors.sol" as CustomErrors;

/**
* @title BondingCurve
Expand Down Expand Up @@ -117,10 +109,7 @@ contract BondingCurve is IBondingCurve {
realNativeReserves = IERC20(WMON).balanceOf(address(this));
realTokenReserves = IERC20(_token).balanceOf(address(this));
lockedToken = _lockedToken;
feeConfig = Fee({
denominator: _feeDenominator,
numerator: _feeNumerator
});
feeConfig = Fee({denominator: _feeDenominator, numerator: _feeNumerator});
isListing = false;
}

Expand All @@ -135,24 +124,15 @@ contract BondingCurve is IBondingCurve {
address _wMon = WMON; //gas savings
address _token = token; //gas savings

(
uint256 _realNativeReserves,
uint256 _realTokenReserves
) = getReserves();
(uint256 _realNativeReserves, uint256 _realTokenReserves) = getReserves();

// Ensure remaining tokens stay above target
require(
_realTokenReserves - amountOut >= lockedToken,
CustomErrors.INVALID_LOCKED_AMOUNT
);
require(_realTokenReserves - amountOut >= lockedToken, CustomErrors.INVALID_LOCKED_AMOUNT);

uint256 balanceWNative;

{
require(
to != _wMon && to != _token,
CustomErrors.INVALID_RECIPIENT
);
require(to != _wMon && to != _token, CustomErrors.INVALID_RECIPIENT);
IERC20(_token).safeTransfer(GNAD, amountOut);

balanceWNative = IERC20(_wMon).balanceOf(address(this));
Expand All @@ -176,22 +156,13 @@ contract BondingCurve is IBondingCurve {

address _wMon = WMON;
address _token = token;
(
uint256 _realNativeReserves,
uint256 _realTokenReserves
) = getReserves();
require(
amountOut <= _realNativeReserves,
CustomErrors.INVALID_AMOUNT_OUT
);
(uint256 _realNativeReserves, uint256 _realTokenReserves) = getReserves();
require(amountOut <= _realNativeReserves, CustomErrors.INVALID_AMOUNT_OUT);

uint256 balanceToken;

{
require(
to != _wMon && to != _token,
CustomErrors.INVALID_RECIPIENT
);
require(to != _wMon && to != _token, CustomErrors.INVALID_RECIPIENT);
IERC20(_wMon).safeTransfer(GNAD, amountOut);
balanceToken = IERC20(_token).balanceOf(address(this));
}
Expand All @@ -213,25 +184,16 @@ contract BondingCurve is IBondingCurve {
require(lock == true, CustomErrors.INVALID_IT_IS_UNLOCKED);
require(!isListing, CustomErrors.INVALID_ALREADY_LISTED);
IBondingCurveFactory _factory = IBondingCurveFactory(FACTORY);
pair = IUniswapV2Factory(_factory.getDexFactory()).createPair(
WMON,
token
);
pair = IUniswapV2Factory(_factory.getDexFactory()).createPair(WMON, token);
uint256 listingFee = _factory.getListingFee();

// A token equivalent to the native token consumed as a listing fee is burned.
// Transfer remaining tokens to the pair
uint256 burnTokenAmount;
{
burnTokenAmount =
realTokenReserves -
((realNativeReserves - listingFee) * virtualToken) /
virtualNative;
burnTokenAmount = realTokenReserves - ((realNativeReserves - listingFee) * virtualToken) / virtualNative;
IToken(token).burn(burnTokenAmount);
IERC20(WMON).safeTransfer(
IGNad(_factory.getGNad()).getFeeVault(),
listingFee
);
IERC20(WMON).safeTransfer(IGNad(_factory.getGNad()).getFeeVault(), listingFee);
}

uint256 listingNativeAmount = IERC20(WMON).balanceOf(address(this));
Expand All @@ -246,14 +208,7 @@ contract BondingCurve is IBondingCurve {

IUniswapV2ERC20(pair).transfer(address(0), liquidity);
isListing = true;
emit Listing(
address(this),
token,
pair,
listingNativeAmount,
listingTokenAmount,
liquidity
);
emit Listing(address(this), token, pair, listingNativeAmount, listingTokenAmount, liquidity);
return pair;
}

Expand All @@ -276,13 +231,7 @@ contract BondingCurve is IBondingCurve {
virtualToken += amountIn;
}

emit Sync(
token,
realNativeReserves,
realTokenReserves,
virtualNative,
virtualToken
);
emit Sync(token, realNativeReserves, realTokenReserves, virtualNative, virtualToken);
}

function _checkTarget() private {
Expand All @@ -299,12 +248,7 @@ contract BondingCurve is IBondingCurve {
* @return nativeReserves The current real Native reserves
* @return tokenReserves The current real token reserves
*/
function getReserves()
public
view
override
returns (uint256 nativeReserves, uint256 tokenReserves)
{
function getReserves() public view override returns (uint256 nativeReserves, uint256 tokenReserves) {
return (realNativeReserves, realTokenReserves);
}

Expand All @@ -327,11 +271,7 @@ contract BondingCurve is IBondingCurve {
* @return denominator The fee denominator
* @return numerator The fee numerator
*/
function getFeeConfig()
external
view
returns (uint8 denominator, uint16 numerator)
{
function getFeeConfig() external view returns (uint8 denominator, uint16 numerator) {
return (feeConfig.denominator, feeConfig.numerator);
}

Expand Down
52 changes: 15 additions & 37 deletions src/BondingCurveFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {IBondingCurveFactory} from "./interfaces/IBondingCurveFactory.sol";
import {IToken} from "./interfaces/IToken.sol";
import {Token} from "./Token.sol";
import {BondingCurve} from "./BondingCurve.sol";
import * as CustomErrors from "./errors/CustomErrors.sol";
import "./errors/CustomErrors.sol" as CustomErrors;

/**
* @title BondingCurveFactory
Expand Down Expand Up @@ -92,20 +92,10 @@ contract BondingCurveFactory is IBondingCurveFactory {
* @return virtualNative Initial virtual NAD reserve
* @return virtualToken Initial virtual token reserve
*/
function create(
address creator,
string memory name,
string memory symbol,
string memory tokenURI
)
function create(address creator, string memory name, string memory symbol, string memory tokenURI)
external
onlyGnad
returns (
address bc,
address token,
uint256 virtualNative,
uint256 virtualToken
)
returns (address bc, address token, uint256 virtualNative, uint256 virtualToken)
{
Config memory _config = getConfig();

Expand All @@ -114,29 +104,21 @@ contract BondingCurveFactory is IBondingCurveFactory {

IToken(token).mint(bc);

IBondingCurve(bc).initialize(
token,
_config.virtualNative,
_config.virtualToken,
_config.k,
_config.targetToken,
_config.feeDenominator,
_config.feeNumerator
);
IBondingCurve(bc)
.initialize(
token,
_config.virtualNative,
_config.virtualToken,
_config.k,
_config.targetToken,
_config.feeDenominator,
_config.feeNumerator
);

bcs[token] = bc;
virtualNative = _config.virtualNative;
virtualToken = _config.virtualToken;
emit Create(
creator,
bc,
token,
tokenURI,
name,
symbol,
virtualNative,
virtualToken
);
emit Create(creator, bc, token, tokenURI, name, symbol, virtualNative, virtualToken);
}

/**
Expand Down Expand Up @@ -226,11 +208,7 @@ contract BondingCurveFactory is IBondingCurveFactory {
* @return denominator Fee denominator
* @return numerator Fee numerator
*/
function getFeeConfig()
public
view
returns (uint8 denominator, uint16 numerator)
{
function getFeeConfig() public view returns (uint8 denominator, uint16 numerator) {
return (config.feeDenominator, config.feeNumerator);
}

Expand Down
36 changes: 5 additions & 31 deletions src/FeeVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@ contract FeeVault is IFeeVault {
uint256 public ownerCount;
uint256 public proposalCount;

// Withdrawal proposal structure
struct WithdrawalProposal {
address receiver;
uint256 amount;
uint256 signatureCount;
mapping(address => bool) hasSignedWithdrawal;
bool executed;
}

/**
* @notice Fallback function to receive WMON
* @dev Only accepts WMON from the WMON contract
Expand All @@ -45,11 +36,7 @@ contract FeeVault is IFeeVault {
* @param _owners Initial list of owner addresses
* @param _requiredSignatures Number of signatures required for withdrawal
*/
constructor(
address _wMon,
address[] memory _owners,
uint256 _requiredSignatures
) {
constructor(address _wMon, address[] memory _owners, uint256 _requiredSignatures) {
require(_wMon != address(0), "ERR_FEE_VAULT_INVALID_WMON_ADDRESS");
require(_owners.length > 0, "ERR_FEE_VAULT_NO_OWNERS");
require(
Expand Down Expand Up @@ -90,10 +77,7 @@ contract FeeVault is IFeeVault {
* @param receiver Address to receive the withdrawn assets
* @param amount Amount of WMON to withdraw
*/
function proposeWithdrawal(
address receiver,
uint256 amount
) external onlyOwner {
function proposeWithdrawal(address receiver, uint256 amount) external onlyOwner {
require(receiver != address(0), "ERR_FEE_VAULT_INVALID_RECEIVER");
require(amount > 0, "ERR_FEE_VAULT_INVALID_AMOUNT");
require(amount <= totalAssets(), "ERR_FEE_VAULT_INSUFFICIENT_BALANCE");
Expand All @@ -115,15 +99,9 @@ contract FeeVault is IFeeVault {
*/
function signWithdrawal(uint256 proposalId) external onlyOwner {
WithdrawalProposal storage proposal = withdrawalProposals[proposalId];
require(
proposal.receiver != address(0),
"ERR_FEE_VAULT_INVALID_PROPOSAL"
);
require(proposal.receiver != address(0), "ERR_FEE_VAULT_INVALID_PROPOSAL");
require(!proposal.executed, "ERR_FEE_VAULT_ALREADY_EXECUTED");
require(
!proposal.hasSignedWithdrawal[msg.sender],
"ERR_FEE_VAULT_ALREADY_SIGNED"
);
require(!proposal.hasSignedWithdrawal[msg.sender], "ERR_FEE_VAULT_ALREADY_SIGNED");

proposal.hasSignedWithdrawal[msg.sender] = true;
proposal.signatureCount++;
Expand All @@ -142,11 +120,7 @@ contract FeeVault is IFeeVault {
* @param proposalId ID of the withdrawal proposal
* @param amount Amount of WMON to withdraw
*/
function _executeWithdrawal(
address receiver,
uint256 proposalId,
uint256 amount
) private {
function _executeWithdrawal(address receiver, uint256 proposalId, uint256 amount) private {
IWMon(WMON).withdraw(amount);

emit WithdrawalExecuted(proposalId, receiver, amount);
Expand Down
Loading
Loading