diff --git a/contracts/src/factory/factory.cairo b/contracts/src/factory/factory.cairo index 810ffde4..871fe4f8 100644 --- a/contracts/src/factory/factory.cairo +++ b/contracts/src/factory/factory.cairo @@ -82,7 +82,8 @@ mod Factory { ref self: ContractState, memecoin_class_hash: ClassHash, lock_manager_address: ContractAddress, - mut exchanges: Span<(SupportedExchanges, ContractAddress)> + mut exchanges: Span<(SupportedExchanges, ContractAddress)>, + mut migrated_tokens: Span, ) { self.memecoin_class_hash.write(memecoin_class_hash); self.lock_manager_address.write(lock_manager_address); @@ -96,6 +97,14 @@ mod Factory { Option::None => { break; } } }; + + // Migrate old tokens, mark them as deployed + loop { + match migrated_tokens.pop_front() { + Option::Some(address) => self.deployed_memecoins.write(*address, true), + Option::None => { break; } + } + }; } #[abi(embed_v0)] diff --git a/contracts/src/tests/fork_tests/utils.cairo b/contracts/src/tests/fork_tests/utils.cairo index 4c0ebdbb..cb0b39b2 100644 --- a/contracts/src/tests/fork_tests/utils.cairo +++ b/contracts/src/tests/fork_tests/utils.cairo @@ -68,9 +68,11 @@ fn deploy_meme_factory(exchanges: Span<(SupportedExchanges, ContractAddress)>) - let contract = declare('Factory'); let mut calldata = array![]; + let migrated_tokens: Span = array![].span(); Serde::serialize(@memecoin_class_hash, ref calldata); Serde::serialize(@lock_manager_address, ref calldata); Serde::serialize(@exchanges.into(), ref calldata); + Serde::serialize(@migrated_tokens, ref calldata); contract.deploy_at(@calldata, MEMEFACTORY_ADDRESS()).expect('UnrugFactory deployment failed') } diff --git a/contracts/src/tests/unit_tests/test_factory.cairo b/contracts/src/tests/unit_tests/test_factory.cairo index dd7f7e90..006036a4 100644 --- a/contracts/src/tests/unit_tests/test_factory.cairo +++ b/contracts/src/tests/unit_tests/test_factory.cairo @@ -1,9 +1,10 @@ use core::option::OptionTrait; +use core::traits::TryInto; use ekubo::types::i129::i129; use openzeppelin::token::erc20::interface::{ERC20ABIDispatcher, ERC20ABIDispatcherTrait}; use snforge_std::{ declare, ContractClassTrait, start_prank, stop_prank, CheatTarget, start_warp, stop_warp, - start_roll, stop_roll + start_roll, stop_roll, get_class_hash, ContractClass }; use starknet::{ContractAddress, contract_address_const}; use unruggable::exchanges::ekubo_adapter::EkuboPoolParameters; @@ -113,6 +114,57 @@ fn test_create_memecoin() { assert_eq!(memecoin.balanceOf(memecoin_factory_address), DEFAULT_INITIAL_SUPPLY(),); } +#[test] +fn test_migrate_memecoin_from_old_factory() { + // Launch + let owner = snforge_std::test_address(); + let (memecoin, memecoin_address) = deploy_memecoin_through_factory_with_owner(owner); + let factory = IFactoryDispatcher { contract_address: MEMEFACTORY_ADDRESS() }; + let eth = ERC20ABIDispatcher { contract_address: ETH_ADDRESS() }; + let block_number = 42; + + // approve spending of eth by factory + let eth_amount: u256 = 1 * pow_256(10, 18); // 1 ETHER + let factory_balance_meme = memecoin.balanceOf(factory.contract_address); + start_prank(CheatTarget::One(eth.contract_address), owner); + eth.approve(factory.contract_address, eth_amount); + stop_prank(CheatTarget::One(eth.contract_address)); + + start_prank(CheatTarget::One(factory.contract_address), owner); + start_warp(CheatTarget::One(memecoin_address), 1); + start_roll(CheatTarget::One(memecoin_address), block_number); + let pair_address = factory + .launch_on_jediswap( + LaunchParameters { + memecoin_address, + transfer_restriction_delay: TRANSFER_RESTRICTION_DELAY, + max_percentage_buy_launch: MAX_PERCENTAGE_BUY_LAUNCH, + quote_address: eth.contract_address, + initial_holders: INITIAL_HOLDERS(), + initial_holders_amounts: INITIAL_HOLDERS_AMOUNTS(), + }, + eth_amount, + DEFAULT_MIN_LOCKTIME, + ); + stop_prank(CheatTarget::One(factory.contract_address)); + + // New factory + let factory_hash = ContractClass { class_hash: get_class_hash(factory.contract_address) }; + let memecoin_hash = get_class_hash(memecoin_address); + let mut calldata = array![]; + let migrated_tokens: Span = array![memecoin_address].span(); + let mut amms: Array<(SupportedExchanges, ContractAddress)> = array![]; + Serde::serialize(@memecoin_hash, ref calldata); + Serde::serialize(@0, ref calldata); + Serde::serialize(@amms.into(), ref calldata); + Serde::serialize(@migrated_tokens, ref calldata); + let new_factory = factory_hash + .deploy_at(@calldata, 'new_factory'.try_into().unwrap()) + .expect('UnrugFactory deployment failed'); + let new_factory_dispatcher = IFactoryDispatcher { contract_address: new_factory }; + assert!(new_factory_dispatcher.is_memecoin(memecoin_address), "should be migrated"); +} + #[test] fn test_launch_memecoin_happy_path() { let owner = snforge_std::test_address(); diff --git a/contracts/src/tests/unit_tests/utils.cairo b/contracts/src/tests/unit_tests/utils.cairo index 6025f470..4cac2a98 100644 --- a/contracts/src/tests/unit_tests/utils.cairo +++ b/contracts/src/tests/unit_tests/utils.cairo @@ -177,9 +177,11 @@ fn deploy_meme_factory(router_address: ContractAddress) -> ContractAddress { let contract = declare('Factory'); let mut calldata = array![]; + let migrated_tokens: Span = array![].span(); Serde::serialize(@memecoin_class_hash, ref calldata); Serde::serialize(@locker_address, ref calldata); Serde::serialize(@amms.into(), ref calldata); + Serde::serialize(@migrated_tokens, ref calldata); contract.deploy_at(@calldata, MEMEFACTORY_ADDRESS()).expect('UnrugFactory deployment failed') }