-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deploy swap router degen #51
base: main
Are you sure you want to change the base?
Changes from 10 commits
b5f4268
af7a063
2ce19da
7db63cf
2d0b4c8
328e16c
a727af3
1cefffa
f45dcda
7cca4b0
ec0317e
9dc9ef5
337d455
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// SPDX-License-Identifier: MIT | ||
// slither-disable-start reentrancy-benign | ||
|
||
pragma solidity 0.8.20; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {console2} from "forge-std/console2.sol"; | ||
import {OpenCreatorTokenFactory} from "src/OpenCreatorTokenFactory.sol"; | ||
|
||
contract DeployOpenFactory is Script { | ||
function run() public { | ||
vm.broadcast(); | ||
OpenCreatorTokenFactory openCreatorTokenFactory = new OpenCreatorTokenFactory(); | ||
|
||
console2.log("Deployed factory contract address %s", address(openCreatorTokenFactory)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// SPDX-License-Identifier: MIT | ||
// slither-disable-start reentrancy-benign | ||
|
||
pragma solidity 0.8.20; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {console2} from "forge-std/console2.sol"; | ||
import {CreatorTokenSwapRouterDegen} from "src/CreatorTokenSwapRouterDegen.sol"; | ||
|
||
contract DeploySwapRouter is Script { | ||
/// @notice Deploy the contract | ||
function run() public { | ||
// Base mainnet addresses | ||
address univRouterAddress = 0x198EF79F1F515F02dFE9e3115eD9fC07183f02fC; | ||
address wethAddress = 0x4200000000000000000000000000000000000006; | ||
address degenAddress = 0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed; | ||
|
||
// Deploy the swap router contract | ||
vm.broadcast(); | ||
CreatorTokenSwapRouter creatorTokenSwapRouter = | ||
new CreatorTokenSwapRouter(_universalRouterAddress, _wethAddress, _usdcAddress); | ||
|
||
console2.log("Deployed router contract address %s", address(creatorTokenSwapRouter)); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// SPDX-License-Identifier: MIT | ||
// slither-disable-start reentrancy-benign | ||
|
||
pragma solidity 0.8.20; | ||
|
||
import {Script} from "forge-std/Script.sol"; | ||
import {console2} from "forge-std/console2.sol"; | ||
import {CreatorToken} from "src/CreatorToken.sol"; | ||
import {SigmoidBondingCurve} from "src/SigmoidBondingCurve.sol"; | ||
|
||
contract TryBondingCurve is Script { | ||
function run() public { | ||
uint128 _basePrice = 100_000_000_000_000; | ||
uint128 _linearPriceSlope = 1_000_000_000_000_000_000_000; | ||
uint128 _inflectionPrice = 100_000_000_000_000_000_000_000; | ||
uint32 _inflectionPoint = 400; | ||
|
||
SigmoidBondingCurve _bondingCurve = | ||
new SigmoidBondingCurve(_basePrice, _linearPriceSlope, _inflectionPrice, _inflectionPoint); | ||
|
||
console2.log("Deployed bonding curve contract address %s", address(_bondingCurve)); | ||
uint256 _tokenNumber = _bondingCurve.priceForTokenNumber(1); | ||
console2.log("print(f'1: {%s/10**18:_}')", _tokenNumber); | ||
|
||
uint256 _tokenNumber2 = _bondingCurve.priceForTokenNumber(2); | ||
console2.log("print(f'2: {%s/10**18:_}')", _tokenNumber2); | ||
|
||
uint256 _tokenNumber3 = _bondingCurve.priceForTokenNumber(3); | ||
console2.log("print(f'3: {%s/10**18:_}')", _tokenNumber3); | ||
|
||
uint256 _tokenNumber10 = _bondingCurve.priceForTokenNumber(10); | ||
console2.log("print(f'10: {%s/10**18:_}')", _tokenNumber10); | ||
|
||
uint256 _tokenNumber100 = _bondingCurve.priceForTokenNumber(100); | ||
console2.log("print(f'100: {%s/10**18:_}')", _tokenNumber100); | ||
|
||
uint256 _tokenNumber200 = _bondingCurve.priceForTokenNumber(200); | ||
console2.log("print(f'200: {%s/10**18:_}')", _tokenNumber200); | ||
|
||
uint256 _tokenNumber300 = _bondingCurve.priceForTokenNumber(300); | ||
console2.log("print(f'300: {%s/10**18:_}')", _tokenNumber300); | ||
|
||
uint256 _tokenNumber400 = _bondingCurve.priceForTokenNumber(400); | ||
console2.log("print(f'400: {%s/10**18:_}')", _tokenNumber400); | ||
|
||
uint256 _tokenNumber500 = _bondingCurve.priceForTokenNumber(500); | ||
console2.log("print(f'500: {%s/10**18:_}')", _tokenNumber500); | ||
|
||
uint256 _tokenNumber600 = _bondingCurve.priceForTokenNumber(600); | ||
console2.log("print(f'600: {%s/10**18:_}')", _tokenNumber600); | ||
|
||
uint256 _tokenNumber700 = _bondingCurve.priceForTokenNumber(700); | ||
console2.log("print(f'700: {%s/10**18:_}')", _tokenNumber700); | ||
|
||
uint256 _tokenNumber800 = _bondingCurve.priceForTokenNumber(800); | ||
console2.log("print(f'800: {%s/10**18:_}')", _tokenNumber800); | ||
|
||
uint256 _tokenNumber900 = _bondingCurve.priceForTokenNumber(900); | ||
console2.log("print(f'900: {%s/10**18:_}')", _tokenNumber900); | ||
|
||
uint256 _tokenNumber1000 = _bondingCurve.priceForTokenNumber(1000); | ||
console2.log("print(f'1000: {%s/10**18:_}')", _tokenNumber1000); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.20; | ||
|
||
import {IUniversalRouter} from "src/lib/IUniversalRouter.sol"; | ||
import {ICreatorToken} from "src/interfaces/ICreatorToken.sol"; | ||
import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; | ||
|
||
/// @title CreatorTokenSwapRouter | ||
/// @notice A contract for swapping ETH to DEGEN and then buying Creator Tokens. | ||
/// @dev Make sure to get a quote for ETH to Creator Token conversion before interacting. | ||
contract CreatorTokenSwapRouter { | ||
/// @notice Uniswap UniversalRouter interface which is used to execute trades. | ||
IUniversalRouter private immutable UNIVERSAL_ROUTER; | ||
/// @notice Address of the Wrapped Ether (WETH) token. | ||
address public immutable WETH_ADDRESS; | ||
Check warning Code scanning / Slither Variable names too similar Warning |
||
/// @notice Address of the DEGEN token. | ||
address public immutable DEGEN_ADDRESS; | ||
Check warning Code scanning / Slither Variable names too similar Warning |
||
|
||
/// @notice Command bytes used for specific operations such as WRAP_ETH(0x0b), | ||
/// V3_SWAP_EXACT_OUT(0x01), and UNWRAP_WETH(0x0c). | ||
bytes private constant COMMANDS = | ||
abi.encodePacked(bytes1(uint8(0x0b)), bytes1(uint8(0x01)), bytes1(uint8(0x0c))); | ||
/// @notice Low fee tier for Uniswap V3 WETH-DEGEN swaps. | ||
bytes3 private constant LOW_FEE_TIER = bytes3(uint24(500)); | ||
|
||
/// @notice Path for swapping WETH to DEGEN. | ||
bytes private path; | ||
|
||
/// @notice Contract constructor sets up the Universal Router and token addresses. | ||
/// @param _universalRouter Address of the Universal Router contract. | ||
/// @param _wethAddress Address of the WETH token contract. | ||
/// @param _degenAddress Address of the DEGEN token contract. | ||
constructor(address _universalRouter, address _wethAddress, address _degenAddress) { | ||
Check notice Code scanning / Slither Missing zero address validation Low
CreatorTokenSwapRouterDegen.constructor(address,address,address)._wethAddress lacks a zero-check on :
- WETH_ADDRESS = _wethAddress Check notice Code scanning / Slither Missing zero address validation Low
CreatorTokenSwapRouterDegen.constructor(address,address,address)._degenAddress lacks a zero-check on :
- DEGEN_ADDRESS = _degenAddress |
||
UNIVERSAL_ROUTER = IUniversalRouter(_universalRouter); | ||
WETH_ADDRESS = _wethAddress; | ||
DEGEN_ADDRESS = _degenAddress; | ||
// WETH -> DEGEN, order is switched because of V3_SWAP_EXACT_OUT | ||
path = | ||
bytes.concat(bytes20(address(DEGEN_ADDRESS)), LOW_FEE_TIER, bytes20(address(WETH_ADDRESS))); | ||
} | ||
|
||
/// @notice Buys a Creator Token with ETH from the caller. | ||
/// @dev Transactions calling this function must include an ETH payment as its `value`. This ETH | ||
/// is then swapped for the equivalent amount of DEGEN needed to purchase the Creator Token. | ||
/// @dev Ensure that the ETH `value` sent with the transaction is equal to or greater than | ||
/// the amount of DEGEN required for the purchase. | ||
/// @dev You can get a quote for the amount of ETH you have to pay to get a certain amount of DEGEN | ||
/// by calling Uniswap's `QuoterV2` contract off-chain. Check Uniswap docs: | ||
/// https://docs.uniswap.org/contracts/v3/reference/periphery/lens/QuoterV2 and `quote` function | ||
/// in `test/SwapRouter.fork.8453.t.sol.sol` | ||
/// @param _creatorToken Address of the Creator Token contract. | ||
/// @param _maxPayment Maximum amount of DEGEN willing to be paid for the token. | ||
/// @return _amountOut The amount of DEGEN paid. | ||
function buyWithEth(address _creatorToken, uint256 _maxPayment) | ||
external | ||
payable | ||
returns (uint256 _amountOut) | ||
{ | ||
_amountOut = buyWithEth(_creatorToken, msg.sender, _maxPayment); | ||
} | ||
|
||
/// @notice Buys creator tokens with ETH and sends them to a specified address. | ||
/// @dev Transactions calling this function must include an ETH payment as its `value`. This ETH | ||
/// is then swapped for the equivalent amount of DEGEN needed to purchase the Creator Token. | ||
/// @dev Ensure that the ETH `value` sent with the transaction is equal to or greater than | ||
/// the amount of DEGEN required for the purchase. | ||
/// @dev You can get a quote for the amount of ETH you have to pay to get a certain amount of DEGEN | ||
/// by calling Uniswap's `QuoterV2` contract off-chain. Check Uniswap docs: | ||
/// https://docs.uniswap.org/contracts/v3/reference/periphery/lens/QuoterV2 and `quote` function | ||
/// in `test/SwapRouter.fork.8453.t.sol.sol` | ||
/// @param _creatorToken The address of the creator token to buy. | ||
/// @param _to The address to send the purchased tokens. | ||
/// @param _maxPayment The maximum amount of DEGEN to be paid. | ||
/// @return _amountOut The amount of DEGEN paid. | ||
function buyWithEth(address _creatorToken, address _to, uint256 _maxPayment) | ||
public | ||
payable | ||
returns (uint256 _amountOut) | ||
{ | ||
_swapEthForDEGEN(_creatorToken, 1, msg.value); | ||
_approveCreatorToken(_creatorToken, _maxPayment); | ||
_amountOut = ICreatorToken(_creatorToken).buy(_to, _maxPayment); | ||
} | ||
|
||
/// @notice Buys a specified number of creator tokens with ETH and sends them to the caller. | ||
/// @dev Transactions calling this function must include an ETH payment as its `value`. This ETH | ||
/// is then swapped for the equivalent amount of DEGEN needed to purchase the Creator Tokens. | ||
/// @dev Ensure that the ETH `value` sent with the transaction is equal to or greater than | ||
/// the amount of DEGEN required for the purchase. | ||
/// @dev You can get a quote for the amount of ETH you have to pay to get a certain amount of DEGEN | ||
/// by calling Uniswap's `QuoterV2` contract off-chain. Check Uniswap docs: | ||
/// https://docs.uniswap.org/contracts/v3/reference/periphery/lens/QuoterV2 and `quote` function | ||
/// in `test/SwapRouter.fork.8453.t.sol.sol` | ||
/// @param _creatorToken The address of the creator token to buy. | ||
/// @param _numOfTokens The number of tokens to buy. | ||
/// @param _maxPayment The maximum amount of DEGEN to be paid. | ||
/// @return _amountOut The amount of DEGEN paid. | ||
function bulkBuyWithEth(address _creatorToken, uint256 _numOfTokens, uint256 _maxPayment) | ||
external | ||
payable | ||
returns (uint256 _amountOut) | ||
{ | ||
_amountOut = bulkBuyWithEth(_creatorToken, msg.sender, _numOfTokens, _maxPayment); | ||
} | ||
|
||
/// @notice Buys a specified number of creator tokens with ETH and sends them to a specified | ||
/// address. | ||
/// @dev Transactions calling this function must include an ETH payment as its `value`. This ETH | ||
/// is then swapped for the equivalent amount of DEGEN needed to purchase the Creator Tokens. | ||
/// @dev Ensure that the ETH `value` sent with the transaction is equal to or greater than | ||
/// the amount of DEGEN required for the purchase. | ||
/// @dev You can get a quote for the amount of ETH you have to pay to get a certain amount of DEGEN | ||
/// by calling Uniswap's `QuoterV2` contract off-chain. Check Uniswap docs: | ||
/// https://docs.uniswap.org/contracts/v3/reference/periphery/lens/QuoterV2 and `quote` function | ||
/// in `test/SwapRouter.fork.8453.t.sol.sol` | ||
/// @param _creatorToken The address of the creator token to buy. | ||
/// @param _to The address to send the purchased creator tokens. | ||
/// @param _numOfTokens The number of tokens to buy. | ||
/// @param _maxPayment The maximum amount of DEGEN to be paid. | ||
/// @return _amountOut The amount of DEGEN paid. | ||
function bulkBuyWithEth( | ||
address _creatorToken, | ||
address _to, | ||
uint256 _numOfTokens, | ||
uint256 _maxPayment | ||
) public payable returns (uint256 _amountOut) { | ||
_swapEthForDEGEN(_creatorToken, _numOfTokens, msg.value); | ||
_approveCreatorToken(_creatorToken, _maxPayment); | ||
_amountOut = ICreatorToken(_creatorToken).bulkBuy(_to, _numOfTokens, _maxPayment); | ||
} | ||
|
||
/// @notice Swaps ETH for DEGEN. | ||
/// @param _creatorToken The address of the creator token. | ||
/// @param _numOfTokens The number of tokens to buy. | ||
/// @param _amountIn The amount of ETH to swap. | ||
function _swapEthForDEGEN(address _creatorToken, uint256 _numOfTokens, uint256 _amountIn) private { | ||
// // Encoding the inputs for V3_SWAP_EXACT_IN | ||
bytes[] memory inputs = new bytes[](3); | ||
(uint256 _tokenPrice, uint256 _creatorFee, uint256 _adminFee) = | ||
ICreatorToken(_creatorToken).priceToBuyNext(_numOfTokens); | ||
// Amount of DEGEN required to purchase `_numOfTokens` | ||
uint256 _amountOut = _tokenPrice + _creatorFee + _adminFee; | ||
// WRAP_ETH | ||
inputs[0] = abi.encode(address(UNIVERSAL_ROUTER), _amountIn); | ||
// V3_SWAP_EXACT_OUT | ||
inputs[1] = abi.encode(address(this), _amountOut, _amountIn, path, false); | ||
// UNWRAP_WETH returns leftover ETH amount to the caller | ||
inputs[2] = abi.encode(msg.sender, 0); | ||
|
||
// // Execute on the UniversalRouter | ||
UNIVERSAL_ROUTER.execute{value: _amountIn}(COMMANDS, inputs, block.timestamp + 60); | ||
} | ||
|
||
/// @dev Approves the creator token contract to transfer DEGEN from this contract. | ||
/// @param _creatorToken The address of the creator token. | ||
/// @param _maxPayment The amount of DEGEN to be spent. | ||
function _approveCreatorToken(address _creatorToken, uint256 _maxPayment) private { | ||
if (IERC20(DEGEN_ADDRESS).allowance(address(this), address(_creatorToken)) < _maxPayment) { | ||
IERC20(DEGEN_ADDRESS).approve(address(_creatorToken), type(uint256).max); | ||
} | ||
} | ||
Comment on lines
+161
to
+165
Check warning Code scanning / Slither Unused return Medium |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.20; | ||
|
||
import {CreatorToken} from "src/CreatorToken.sol"; | ||
import {SigmoidBondingCurve} from "src/SigmoidBondingCurve.sol"; | ||
import {IERC20} from "openzeppelin/token/ERC20/IERC20.sol"; | ||
import {IShowtimeVerifier, Attestation} from "src/lib/IShowtimeVerifier.sol"; | ||
|
||
/// @notice Identical as CreatorTokenFactory, without verifier logic. | ||
contract OpenCreatorTokenFactory { | ||
/// @notice All the configuration parameters required to deploy a CreatorToken and its | ||
/// SigmoidBondingCurve. | ||
/// @param name The name of the ERC721 token. | ||
/// @param symbol The symbol of the ERC721 token. | ||
/// @param tokenURI The URI for the creator token. | ||
/// @param creator Address of the creator. | ||
/// @param creatorFee Creator fee in BIPs. | ||
/// @param creatorRoyalty Creator royalty fee in BIPs. | ||
/// @param admin Address of the admin. | ||
/// @param adminFee Admin fee in BIPs. | ||
/// @param referrer Address of the referrer. | ||
/// @param payToken ERC20 token used for payments. | ||
/// @param basePrice The base price at the start of the curve. | ||
/// @param linearPriceSlope The linear coefficient used to fine tune the curve. | ||
/// @param inflectionPrice The price at the point where the curve switches from quadratic to | ||
/// square root. | ||
/// @param inflectionPoint Where the curve switches from quadratic to square root. | ||
struct DeploymentConfig { | ||
string name; | ||
string symbol; | ||
string tokenURI; | ||
address creator; | ||
uint256 creatorFee; | ||
uint96 creatorRoyalty; | ||
address admin; | ||
uint256 adminFee; | ||
address referrer; | ||
IERC20 payToken; | ||
uint128 basePrice; | ||
uint128 linearPriceSlope; | ||
uint128 inflectionPrice; | ||
uint32 inflectionPoint; | ||
} | ||
|
||
/// @notice Emitted when a new CreatorToken and SigmoidBondingCurve pair is successfully | ||
/// deployed. | ||
/// @param creatorToken The address of the newly deployed CreatorToken contract. | ||
/// @param bondingCurve The address of the newly deployed SigmoidBondingCurve contract. | ||
/// @param config The config object used to execute this deployment. | ||
event CreatorTokenDeployed( | ||
CreatorToken indexed creatorToken, | ||
SigmoidBondingCurve indexed bondingCurve, | ||
DeploymentConfig config | ||
); | ||
|
||
/// @notice Deploys a CreatorToken and SigmoidBondingCurve pair for the given configuration. | ||
/// @param _config The configuration data for the would-be token and bonding curve contracts. | ||
/// @return _creatorToken The address of the newly deployed CreatorToken contract. | ||
function deploy(DeploymentConfig memory _config) external returns (CreatorToken _creatorToken) { | ||
SigmoidBondingCurve _bondingCurve = | ||
new SigmoidBondingCurve(_config.basePrice, _config.linearPriceSlope, _config.inflectionPrice, _config.inflectionPoint); | ||
|
||
_creatorToken = new CreatorToken( | ||
_config.name, | ||
_config.symbol, | ||
_config.tokenURI, | ||
_config.creator, | ||
_config.creatorFee, | ||
_config.creatorRoyalty, | ||
_config.admin, | ||
_config.adminFee, | ||
_config.referrer, | ||
_config.payToken, | ||
_bondingCurve | ||
); | ||
emit CreatorTokenDeployed(_creatorToken, _bondingCurve, _config); | ||
} | ||
} |
Check warning
Code scanning / Slither
Variable names too similar Warning