Skip to content

Commit

Permalink
chore: exposes sell function
Browse files Browse the repository at this point in the history
  • Loading branch information
fabianschu committed Nov 19, 2024
1 parent bb254da commit c013d58
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 171 deletions.
3 changes: 2 additions & 1 deletion src/experimental/factories/Immutable_PIM_Factory_v1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ contract Immutable_PIM_Factory_v1 is
address fundingManager = address(orchestrator.fundingManager());
// enable bonding curve to mint issuance token
issuanceToken.setMinter(fundingManager, true);
issuanceToken.setMinter(address(this), false);

// if initial purchase amount set execute first purchase from curve
if (initialPurchaseAmount > 0) {
Expand Down Expand Up @@ -142,6 +141,8 @@ contract Immutable_PIM_Factory_v1 is
} catch {}
}

// remove factory as minter
issuanceToken.setMinter(address(this), false);
// renounce token ownership
issuanceToken.renounceOwnership();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {IOrchestrator_v1} from
"src/orchestrator/interfaces/IOrchestrator_v1.sol";
import {IBondingCurveBase_v1} from
"@fm/bondingCurve/abstracts/BondingCurveBase_v1.sol";
import {IRedeemingBondingCurveBase_v1} from
"@fm/bondingCurve/interfaces/IRedeemingBondingCurveBase_v1.sol";
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
import {IFundingManager_v1} from "@fm/IFundingManager_v1.sol";
import {FM_BC_Bancor_Redeeming_VirtualSupply_v1} from
Expand Down Expand Up @@ -97,7 +99,9 @@ contract LM_ImmutableMigration_v1 is
* @param amountIn The maximum amount of collateral tokens to spend
* @param recipient The address to receive the purchased tokens
*/
function buyForUpTo(uint amountIn, address recipient) external {
function buyForUpTo(address recipient, uint amountIn, uint minAmountOut)
external
{
address fundingManager = address(__Module_orchestrator.fundingManager());
IERC20 collateralToken = __Module_orchestrator.fundingManager().token();

Expand All @@ -115,7 +119,7 @@ contract LM_ImmutableMigration_v1 is
// Use valid amount to buy from curve
if (validAmountIn > 0) {
IBondingCurveBase_v1(fundingManager).buyFor(
recipient, validAmountIn, 1
recipient, validAmountIn, minAmountOut
);
}

Expand All @@ -129,14 +133,35 @@ contract LM_ImmutableMigration_v1 is
collateralToken.balanceOf(fundingManager)
== migrationThreshold - initialVirtualCollateralSupply
) {
// Close buying on the funding manager
// Close buying & selling on the funding manager
IBondingCurveBase_v1(fundingManager).closeBuy();
IRedeemingBondingCurveBase_v1(fundingManager).closeSell();

// Initiate graduation
_graduate();
}
}

function sellFor(address recipient, uint amountIn, uint minAmountOut)
external
{
FM_BC_Bancor_Redeeming_VirtualSupply_v1 fundingManager =
FM_BC_Bancor_Redeeming_VirtualSupply_v1(
address(__Module_orchestrator.fundingManager())
);
IERC20Issuance_v1 issuanceToken =
IERC20Issuance_v1(fundingManager.getIssuanceToken());

// Transfer issuance tokens from sender to this contract
issuanceToken.transferFrom(msg.sender, address(this), amountIn);

// Approve funding manager to spend issuance token
issuanceToken.approve(address(fundingManager), amountIn);

// Make sell order
fundingManager.sellTo(recipient, amountIn, minAmountOut);
}

function _checkBuyExceedsThreshold(uint amountIn)
internal
view
Expand Down
32 changes: 1 addition & 31 deletions src/experimental/modules/ImmutableMigration/UniswapV2Adapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ contract UniswapV2Adapter is IDexAdapter_v1 {

function createLiquidity(address tokenA, address tokenB, address to)
external
override
returns (uint liquidity)
{
factory.createPair(tokenA, tokenB);
Expand All @@ -45,7 +44,7 @@ contract UniswapV2Adapter is IDexAdapter_v1 {
IERC20(tokenB).approve(address(router), amountB);

// Add liquidity through the router
(,, liquidity) = router.addLiquidity(
router.addLiquidity(
tokenA,
tokenB,
amountA,
Expand All @@ -56,33 +55,4 @@ contract UniswapV2Adapter is IDexAdapter_v1 {
block.timestamp + 10 minutes
);
}

// function createPoolAndAddLiquidity(
// address tokenA,
// address tokenB,
// uint amountADesired,
// uint amountBDesired,
// uint amountAMin,
// uint amountBMin,
// address to
// ) external override returns (uint liquidity) {
// // Create the pair if it doesn't exist
// if (factory.getPair(tokenA, tokenB) == address(0)) {
// factory.createPair(tokenA, tokenB);
// }

// //

// // Add liquidity through the router
// (,, liquidity) = router.addLiquidity(
// tokenA,
// tokenB,
// amountADesired,
// amountBDesired,
// amountAMin,
// amountBMin,
// to,
// block.timestamp
// );
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import {IERC20PaymentClientBase_v1} from
"@lm/interfaces/IERC20PaymentClientBase_v1.sol";

interface ILM_ImmutableMigration_v1 {
function buyForUpTo(uint amountIn, address recipient) external;
function buyForUpTo(address recipient, uint amountIn, uint minAmountOut)
external;
}
168 changes: 40 additions & 128 deletions test/experimental/e2e/ImmutableMigrationE2E.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ contract LM_ImmutableMigration_v1E2E is ExtendedE2ETest {
if (amountIn == 0) return;

// Bound input to range below threshold
amountIn = bound(amountIn, 1, COLLATERAL_MIGRATION_THRESHOLD - 1);
amountIn = bound(amountIn, 1 ether, COLLATERAL_MIGRATION_THRESHOLD - 1);

mintAndApprove(amountIn);

Expand All @@ -187,7 +187,7 @@ contract LM_ImmutableMigration_v1E2E is ExtendedE2ETest {
uint buyerIssuanceBalanceBefore = issuanceToken.balanceOf(address(this));

// Execute buy
migrationModule.buyForUpTo(amountIn, address(this));
migrationModule.buyForUpTo(address(this), amountIn, 1);

// Verify balances changed correctly
assertLt(
Expand All @@ -213,14 +213,20 @@ contract LM_ImmutableMigration_v1E2E is ExtendedE2ETest {

vm.expectEmit(true, true, true, true);
emit IBondingCurveBase_v1.BuyingDisabled();
migrationModule.buyForUpTo(amountIn, address(this));
migrationModule.buyForUpTo(address(this), amountIn, 1);

assertFalse(
FM_BC_Bancor_Redeeming_VirtualSupply_v1(
address(orchestrator.fundingManager())
).buyIsOpen(),
"Buying should be closed"
);
assertFalse(
FM_BC_Bancor_Redeeming_VirtualSupply_v1(
address(orchestrator.fundingManager())
).sellIsOpen(),
"Selling should be closed"
);
assertEq(
token.balanceOf(address(this)),
amountIn - COLLATERAL_MIGRATION_THRESHOLD,
Expand All @@ -233,131 +239,37 @@ contract LM_ImmutableMigration_v1E2E is ExtendedE2ETest {
);
}

// // Test
// function test_e2e_MigrateLiquidityLifecycle() public {
// //--------------------------------------------------------------------------
// // Orchestrator Initialization
// //--------------------------------------------------------------------------

// // Set WorkflowConfig
// IOrchestratorFactory_v1.WorkflowConfig memory workflowConfig =
// IOrchestratorFactory_v1.WorkflowConfig({
// independentUpdates: false,
// independentUpdateAdmin: address(0)
// });

// // Set Orchestrator
// IOrchestrator_v1 orchestrator =
// _create_E2E_Orchestrator(workflowConfig, moduleConfigurations);

// // Set FundingManager
// FM_BC_Bancor_Redeeming_VirtualSupply_v1 fundingManager =
// FM_BC_Bancor_Redeeming_VirtualSupply_v1(
// address(orchestrator.fundingManager())
// );

// // Find and Set Migration Manager
// LM_PC_MigrateLiquidity_UniswapV2_v1 migrationManager;
// address[] memory modulesList = orchestrator.listModules();
// for (uint i; i < modulesList.length; ++i) {
// if (
// ERC165Upgradeable(modulesList[i]).supportsInterface(
// type(ILM_PC_MigrateLiquidity_UniswapV2_v1).interfaceId
// )
// ) {
// migrationManager =
// LM_PC_MigrateLiquidity_UniswapV2_v1(modulesList[i]);
// break;
// }
// }

// // Test Lifecycle
// //--------------------------------------------------------------------------

// // 1. Set FundingManager as Minter
// issuanceToken.setMinter(address(fundingManager), true);

// // 1.1. Set Migration Manager As Minter
// issuanceToken.setMinter(address(migrationManager), true);

// // 2. Mint Collateral To Buy From the FundingManager
// token.mint(address(this), BUY_FROM_FUNDING_MANAGER_AMOUNT);

// // 3. Calculate Minimum Amount Out
// uint buf_minAmountOut = fundingManager.calculatePurchaseReturn(
// BUY_FROM_FUNDING_MANAGER_AMOUNT
// ); // buffer variable to store the minimum amount out on calls to the buy and sell functions

// // 4. Buy from the FundingManager
// vm.startPrank(address(this));
// {
// // 4.1. Approve tokens to fundingManager.
// token.approve(
// address(fundingManager), BUY_FROM_FUNDING_MANAGER_AMOUNT
// );
// // 4.2. Deposit tokens, i.e. fund the fundingmanager.
// fundingManager.buy(
// BUY_FROM_FUNDING_MANAGER_AMOUNT, buf_minAmountOut
// );
// // 4.3. After the deposit, check that the user has received them
// assertTrue(
// issuanceToken.balanceOf(address(this)) > 0,
// "User should have received issuance tokens after deposit"
// );
// }
// vm.stopPrank();

// // 5. Check no pool exists yet
// address lpTokenAddress =
// uniswapFactory.getPair(address(token), address(issuanceToken));

// assertEq(lpTokenAddress, address(0), "Pool should not exist yet");

// // 6. Set migration manager instance
// ILM_PC_MigrateLiquidity_UniswapV2_v1.LiquidityMigrationConfig memory
// migration = migrationManager.getMigrationConfig();

// ILM_PC_MigrateLiquidity_UniswapV2_v1.LiquidityMigrationResult memory
// migrationResult;

// // 7. Execute migration
// vm.startPrank(address(this));
// migrationResult = migrationManager.executeMigration();
// vm.stopPrank();

// bool executed = migrationManager.getExecuted();

// // 8. Verify pool creation and liquidity
// lpTokenAddress =
// uniswapFactory.getPair(address(token), address(issuanceToken));
// assertTrue(lpTokenAddress != address(0), "Pool should exist");

// // 9.1. Get pair
// IUniswapV2Pair pair = IUniswapV2Pair(lpTokenAddress);

// // 9.2. Get reserves
// (uint112 reserve0, uint112 reserve1,) = pair.getReserves();

// // 9.3. Verify reserves based on token ordering
// if (pair.token0() == address(token)) {
// assertGt(reserve0, 0, "Token reserves should be positive");
// assertGt(reserve1, 0, "IssuanceToken reserves should be positive");
// } else {
// assertGt(reserve0, 0, "IssuanceToken reserves should be positive");
// assertGt(reserve1, 0, "Token reserves should be positive");
// }

// // 10. Verify migration completion
// migration = migrationManager.getMigrationConfig();
// assertTrue(executed, "Migration should be marked as executed");

// // 11. Verify LP tokens are received by the migration manager
// assertGt(
// IERC20(migrationResult.lpTokenAddress).balanceOf(address(this)),
// 0,
// "Script should have received LP tokens"
// );
// }
function test_sellFor(uint amountIn) public {
// Bound input to range below threshold
amountIn = bound(amountIn, 1 ether, COLLATERAL_MIGRATION_THRESHOLD - 1);
mintAndApprove(amountIn);

assertEq(
issuanceToken.balanceOf(address(this)),
0,
"Buyer should not hold issuance tokens initially"
);

migrationModule.buyForUpTo(address(this), amountIn, 1);

uint issuanceBalanceBeforeSale = issuanceToken.balanceOf(address(this));
assertGt(
issuanceBalanceBeforeSale,
0,
"Buyer should have received issuance tokens"
);
issuanceToken.approve(
address(migrationModule), issuanceBalanceBeforeSale
);

migrationModule.sellFor(address(this), issuanceBalanceBeforeSale, 1);
uint issuanceBalanceAfterSale = issuanceToken.balanceOf(address(this));
assertEq(
issuanceBalanceAfterSale,
0,
"Buyer should not hold issuance tokens after sale"
);
}

//--------------------------------------------------------------------------
// Custom Assertions
Expand Down
Loading

0 comments on commit c013d58

Please sign in to comment.