Skip to content

Commit

Permalink
Setup Transfer restriction delay at launch (#136)
Browse files Browse the repository at this point in the history
with this PR, transfer restriction delay has to be provided at memecoin
launch instead of creation.
  • Loading branch information
0xChqrles authored Jan 10, 2024
1 parent 6685823 commit 1323cfc
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 62 deletions.
11 changes: 5 additions & 6 deletions contracts/src/factory/factory.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,9 @@ mod Factory {
initial_supply: u256,
initial_holders: Span<ContractAddress>,
initial_holders_amounts: Span<u256>,
transfer_limit_delay: u64,
contract_address_salt: felt252,
) -> ContractAddress {
let mut calldata = array![
owner.into(), transfer_limit_delay.into(), name.into(), symbol.into()
];
let mut calldata = array![owner.into(), name.into(), symbol.into()];
Serde::serialize(@initial_supply, ref calldata);
Serde::serialize(@initial_holders.into(), ref calldata);
Serde::serialize(@initial_holders_amounts.into(), ref calldata);
Expand All @@ -128,6 +125,7 @@ mod Factory {
fn launch_on_jediswap(
ref self: ContractState,
memecoin_address: ContractAddress,
transfer_restriction_delay: u64,
quote_address: ContractAddress,
quote_amount: u256,
unlock_time: u64,
Expand All @@ -152,7 +150,7 @@ mod Factory {
}
);

memecoin.set_launched(LiquidityType::ERC20(pair_address));
memecoin.set_launched(LiquidityType::ERC20(pair_address), :transfer_restriction_delay);
self
.emit(
MemecoinLaunched {
Expand All @@ -165,6 +163,7 @@ mod Factory {
fn launch_on_ekubo(
ref self: ContractState,
memecoin_address: ContractAddress,
transfer_restriction_delay: u64,
quote_address: ContractAddress,
ekubo_parameters: EkuboPoolParameters,
) -> (u64, EkuboLP) {
Expand All @@ -184,7 +183,7 @@ mod Factory {
additional_parameters: ekubo_parameters
);

memecoin.set_launched(LiquidityType::NFT(id));
memecoin.set_launched(LiquidityType::NFT(id), :transfer_restriction_delay);
self
.emit(
MemecoinLaunched {
Expand Down
6 changes: 4 additions & 2 deletions contracts/src/factory/interface.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ trait IFactory<TContractState> {
/// * `initial_supply` - The initial supply of the Memecoin.
/// * `initial_holders` - An array containing the initial holders' addresses.
/// * `initial_holders_amounts` - An array containing the initial amounts held by each corresponding initial holder.
/// * `transfer_limit_delay` - The delay in seconds during which transfers will be limited to a % of max supply after launch.
/// * `quote_token` - The address of the quote token
/// * `contract_address_salt` - A unique salt value for contract deployment
///
Expand All @@ -34,7 +33,6 @@ trait IFactory<TContractState> {
initial_supply: u256,
initial_holders: Span<ContractAddress>,
initial_holders_amounts: Span<u256>,
transfer_limit_delay: u64,
contract_address_salt: felt252
) -> ContractAddress;

Expand All @@ -47,6 +45,7 @@ trait IFactory<TContractState> {
/// # Arguments
///
/// * `memecoin_address` - The address of the memecoin contract.
/// * `transfer_restriction_delay` - The delay in seconds during which transfers will be limited to a % of max supply after launch.
/// * `quote_address` - The address of the quote token contract.
/// * `quote_amount` - The amount of quote tokens to add as liquidity.
/// * `unlock_time` - The timestamp when the liquidity can be unlocked.
Expand All @@ -65,6 +64,7 @@ trait IFactory<TContractState> {
fn launch_on_jediswap(
ref self: TContractState,
memecoin_address: ContractAddress,
transfer_restriction_delay: u64,
quote_address: ContractAddress,
quote_amount: u256,
unlock_time: u64,
Expand All @@ -78,6 +78,7 @@ trait IFactory<TContractState> {
/// # Arguments
///
/// * `memecoin_address` - The address of the memecoin contract.
/// * `transfer_restriction_delay` - The delay in seconds during which transfers will be limited to a % of max supply after launch.
/// * `quote_address` - The address of the quote token contract.
/// * `ekubo_parameters` - The parameters for the ekubo liquidity pool, including:
/// - `fee` - The fee for the liquidity pair.
Expand All @@ -100,6 +101,7 @@ trait IFactory<TContractState> {
fn launch_on_ekubo(
ref self: TContractState,
memecoin_address: ContractAddress,
transfer_restriction_delay: u64,
quote_address: ContractAddress,
ekubo_parameters: EkuboPoolParameters,
) -> (u64, EkuboLP);
Expand Down
4 changes: 3 additions & 1 deletion contracts/src/tests/fork_tests/test_ekubo.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use unruggable::tests::fork_tests::utils::{
};
use unruggable::tests::unit_tests::utils::{
OWNER, DEFAULT_MIN_LOCKTIME, pow_256, LOCK_MANAGER_ADDRESS, MEMEFACTORY_ADDRESS, RECIPIENT,
ALICE, DefaultTxInfoMock
ALICE, DefaultTxInfoMock, TRANSFER_RESTRICTION_DELAY,
};
use unruggable::token::interface::{
IUnruggableMemecoinDispatcher, IUnruggableMemecoinDispatcherTrait
Expand All @@ -48,6 +48,7 @@ fn launch_memecoin_on_ekubo(
let (id, position) = factory
.launch_on_ekubo(
memecoin_address,
TRANSFER_RESTRICTION_DELAY,
quote_address,
EkuboPoolParameters { fee, tick_spacing, starting_tick, bound }
);
Expand Down Expand Up @@ -616,6 +617,7 @@ fn test_cant_launch_twice() {
let (id, position) = factory
.launch_on_ekubo(
memecoin_address,
TRANSFER_RESTRICTION_DELAY,
quote_address,
EkuboPoolParameters {
fee: 0xc49ba5e353f7d00000000000000000,
Expand Down
6 changes: 4 additions & 2 deletions contracts/src/tests/fork_tests/test_jediswap.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use unruggable::tests::addresses::{JEDI_FACTORY_ADDRESS, JEDI_ROUTER_ADDRESS, ET
use unruggable::tests::fork_tests::utils::{deploy_memecoin_through_factory_with_owner, sort_tokens};
use unruggable::tests::unit_tests::utils::{
OWNER, DEFAULT_MIN_LOCKTIME, pow_256, LOCK_MANAGER_ADDRESS, MEMEFACTORY_ADDRESS,
deploy_eth_with_owner
deploy_eth_with_owner, TRANSFER_RESTRICTION_DELAY
};
use unruggable::token::interface::{IUnruggableMemecoinDispatcherTrait};
use unruggable::token::memecoin::LiquidityType;
Expand All @@ -37,7 +37,9 @@ fn test_jediswap_integration() {
stop_prank(CheatTarget::One(quote.contract_address));

let pair_address = factory
.launch_on_jediswap(memecoin_address, quote_address, amount, unlock_time);
.launch_on_jediswap(
memecoin_address, TRANSFER_RESTRICTION_DELAY, quote_address, amount, unlock_time
);

let pair = IJediswapPairDispatcher { contract_address: pair_address };

Expand Down
4 changes: 1 addition & 3 deletions contracts/src/tests/fork_tests/utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use unruggable::tests::addresses::{
};
use unruggable::tests::unit_tests::utils::{
deploy_locker, deploy_eth_with_owner, NAME, SYMBOL, DEFAULT_INITIAL_SUPPLY, INITIAL_HOLDERS,
INITIAL_HOLDERS_AMOUNTS, TRANSFER_LIMIT_DELAY, SALT, DefaultTxInfoMock, OWNER, TOKEN0_ADDRESS,
MEMEFACTORY_ADDRESS
INITIAL_HOLDERS_AMOUNTS, SALT, DefaultTxInfoMock, OWNER, TOKEN0_ADDRESS, MEMEFACTORY_ADDRESS
};
use unruggable::token::interface::{
IUnruggableMemecoinDispatcher, IUnruggableMemecoinDispatcherTrait
Expand Down Expand Up @@ -109,7 +108,6 @@ fn deploy_memecoin_through_factory_with_owner(
initial_supply: DEFAULT_INITIAL_SUPPLY(),
initial_holders: INITIAL_HOLDERS(),
initial_holders_amounts: INITIAL_HOLDERS_AMOUNTS(),
transfer_limit_delay: TRANSFER_LIMIT_DELAY,
contract_address_salt: SALT(),
);
stop_prank(CheatTarget::One(memecoin_factory.contract_address));
Expand Down
20 changes: 15 additions & 5 deletions contracts/src/tests/unit_tests/test_factory.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use unruggable::tests::unit_tests::utils::{
SYMBOL, DEFAULT_INITIAL_SUPPLY, INITIAL_HOLDERS, INITIAL_HOLDERS_AMOUNTS, SALT,
deploy_memecoin_through_factory, MEMEFACTORY_ADDRESS,
deploy_memecoin_through_factory_with_owner, pow_256, LOCK_MANAGER_ADDRESS, DEFAULT_MIN_LOCKTIME,
deploy_and_launch_memecoin
deploy_and_launch_memecoin, TRANSFER_RESTRICTION_DELAY
};
use unruggable::token::interface::{
IUnruggableMemecoin, IUnruggableMemecoinDispatcher, IUnruggableMemecoinDispatcherTrait
Expand Down Expand Up @@ -97,7 +97,6 @@ fn test_create_memecoin() {
initial_supply: DEFAULT_INITIAL_SUPPLY(),
initial_holders: INITIAL_HOLDERS(),
initial_holders_amounts: INITIAL_HOLDERS_AMOUNTS(),
transfer_limit_delay: 1000,
contract_address_salt: SALT(),
);
stop_prank(CheatTarget::One(memecoin_factory.contract_address));
Expand Down Expand Up @@ -140,7 +139,11 @@ fn test_launch_memecoin_happy_path() {
start_warp(CheatTarget::One(memecoin_address), 1);
let pair_address = factory
.launch_on_jediswap(
memecoin_address, eth.contract_address, eth_amount, DEFAULT_MIN_LOCKTIME,
memecoin_address,
TRANSFER_RESTRICTION_DELAY,
eth.contract_address,
eth_amount,
DEFAULT_MIN_LOCKTIME,
);
stop_prank(CheatTarget::One(factory.contract_address));
stop_warp(CheatTarget::One(memecoin_address));
Expand Down Expand Up @@ -191,7 +194,11 @@ fn test_launch_memecoin_already_launched() {
start_prank(CheatTarget::One(factory.contract_address), OWNER());
let pair_address = factory
.launch_on_jediswap(
memecoin_address, eth.contract_address, eth_amount, DEFAULT_MIN_LOCKTIME,
memecoin_address,
TRANSFER_RESTRICTION_DELAY,
eth.contract_address,
eth_amount,
DEFAULT_MIN_LOCKTIME,
);
}

Expand All @@ -201,7 +208,9 @@ fn test_launch_memecoin_not_owner() {
let (memecoin, memecoin_address) = deploy_memecoin_through_factory();
let factory = IFactoryDispatcher { contract_address: MEMEFACTORY_ADDRESS() };
let pair_address = factory
.launch_on_jediswap(memecoin_address, ETH_ADDRESS(), 1, DEFAULT_MIN_LOCKTIME,);
.launch_on_jediswap(
memecoin_address, TRANSFER_RESTRICTION_DELAY, ETH_ADDRESS(), 1, DEFAULT_MIN_LOCKTIME,
);
}

#[test]
Expand All @@ -218,6 +227,7 @@ fn test_launch_memecoin_amm_not_whitelisted() {
let pool_address = factory
.launch_on_ekubo(
memecoin_address,
TRANSFER_RESTRICTION_DELAY,
eth.contract_address,
EkuboPoolParameters {
fee: 0, tick_spacing: 0, starting_tick: i129 { sign: false, mag: 0 }, bound: 0
Expand Down
8 changes: 4 additions & 4 deletions contracts/src/tests/unit_tests/test_memecoin_erc20.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use starknet::{ContractAddress, contract_address_const};
use unruggable::exchanges::{SupportedExchanges};
use unruggable::tests::unit_tests::utils::{
OWNER, NAME, SYMBOL, DEFAULT_INITIAL_SUPPLY, RECIPIENT, SPENDER, deploy_locker, INITIAL_HOLDERS,
INITIAL_HOLDERS_AMOUNTS, TRANSFER_LIMIT_DELAY, DefaultTxInfoMock, deploy_standalone_memecoin
INITIAL_HOLDERS_AMOUNTS, TRANSFER_RESTRICTION_DELAY, DefaultTxInfoMock,
deploy_standalone_memecoin
};
use unruggable::token::interface::{
IUnruggableMemecoinDispatcher, IUnruggableMemecoinDispatcherTrait
Expand All @@ -23,7 +24,7 @@ mod erc20_metadata {
use starknet::{ContractAddress, contract_address_const};
use super::{
deploy_standalone_memecoin, OWNER, NAME, SYMBOL, DEFAULT_INITIAL_SUPPLY, RECIPIENT, SPENDER,
deploy_locker, TRANSFER_LIMIT_DELAY
deploy_locker
};
use unruggable::token::interface::{
IUnruggableMemecoinDispatcher, IUnruggableMemecoinDispatcherTrait
Expand Down Expand Up @@ -58,8 +59,7 @@ mod erc20_entrypoints {
use starknet::{ContractAddress, contract_address_const};
use super::{
deploy_standalone_memecoin, OWNER, NAME, SYMBOL, DEFAULT_INITIAL_SUPPLY, RECIPIENT, SPENDER,
deploy_locker, TRANSFER_LIMIT_DELAY, INITIAL_HOLDERS, DefaultTxInfoMock,
INITIAL_HOLDERS_AMOUNTS
deploy_locker, INITIAL_HOLDERS, DefaultTxInfoMock, INITIAL_HOLDERS_AMOUNTS
};
use unruggable::token::interface::{
IUnruggableMemecoinDispatcher, IUnruggableMemecoinDispatcherTrait
Expand Down
29 changes: 10 additions & 19 deletions contracts/src/tests/unit_tests/test_unruggable_memecoin.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use starknet::{ContractAddress, contract_address_const};
use unruggable::exchanges::{SupportedExchanges};
use unruggable::tests::unit_tests::utils::{
OWNER, NAME, SYMBOL, DEFAULT_INITIAL_SUPPLY, RECIPIENT, SPENDER, deploy_locker, INITIAL_HOLDERS,
INITIAL_HOLDERS_AMOUNTS, TRANSFER_LIMIT_DELAY, DefaultTxInfoMock,
INITIAL_HOLDERS_AMOUNTS, TRANSFER_RESTRICTION_DELAY, DefaultTxInfoMock,
deploy_memecoin_through_factory
};
use unruggable::token::interface::{
Expand All @@ -33,7 +33,7 @@ mod test_constructor {
deploy_eth_with_owner, OWNER, NAME, SYMBOL, DEFAULT_INITIAL_SUPPLY, INITIAL_HOLDERS,
INITIAL_HOLDER_1, INITIAL_HOLDER_2, INITIAL_HOLDERS_AMOUNTS, SALT, DefaultTxInfoMock,
deploy_memecoin_through_factory, ETH_ADDRESS, deploy_memecoin_through_factory_with_owner,
JEDI_ROUTER_ADDRESS, MEMEFACTORY_ADDRESS, ALICE, BOB, TRANSFER_LIMIT_DELAY, pow_256,
JEDI_ROUTER_ADDRESS, MEMEFACTORY_ADDRESS, ALICE, BOB, TRANSFER_RESTRICTION_DELAY, pow_256,
LOCK_MANAGER_ADDRESS, JEDI_FACTORY_ADDRESS
};
use unruggable::token::UnruggableMemecoin;
Expand All @@ -51,7 +51,6 @@ mod test_constructor {
UnruggableMemecoin::constructor(
ref memecoin,
OWNER(),
TRANSFER_LIMIT_DELAY,
NAME(),
SYMBOL(),
DEFAULT_INITIAL_SUPPLY(),
Expand All @@ -65,10 +64,6 @@ mod test_constructor {
);

// Check internals that must be set upon deployment
assert(
memecoin.transfer_restriction_delay.read() == TRANSFER_LIMIT_DELAY,
'wrong transfer limit delay'
);
assert(
memecoin.team_allocation.read() == 2_100_000 * pow_256(10, 18), 'wrong team allocation'
); // 10% of supply
Expand All @@ -88,7 +83,6 @@ mod test_constructor {
UnruggableMemecoin::constructor(
ref state,
OWNER(),
TRANSFER_LIMIT_DELAY,
NAME(),
SYMBOL(),
DEFAULT_INITIAL_SUPPLY(),
Expand Down Expand Up @@ -119,7 +113,6 @@ mod test_constructor {
UnruggableMemecoin::constructor(
ref state,
OWNER(),
TRANSFER_LIMIT_DELAY,
NAME(),
SYMBOL(),
DEFAULT_INITIAL_SUPPLY(),
Expand All @@ -131,17 +124,14 @@ mod test_constructor {
#[test]
#[should_panic(expected: ('Max team allocation reached',))]
fn test_constructor_too_much_team_alloc_should_fail() {
let mut calldata = array![
OWNER().into(), 'locker', TRANSFER_LIMIT_DELAY.into(), NAME().into(), SYMBOL().into()
];
let mut calldata = array![OWNER().into(), 'locker', NAME().into(), SYMBOL().into()];
// Allocation over 10% (over 2.1M)
let alloc_holder_1 = 1_050_000 * pow_256(10, 18);
let alloc_holder_2 = 1_050_001 * pow_256(10, 18);
let mut state = UnruggableMemecoin::contract_state_for_testing();
UnruggableMemecoin::constructor(
ref state,
OWNER(),
TRANSFER_LIMIT_DELAY,
NAME(),
SYMBOL(),
DEFAULT_INITIAL_SUPPLY(),
Expand Down Expand Up @@ -171,7 +161,7 @@ mod memecoin_entrypoints {
INITIAL_HOLDER_1, INITIAL_HOLDER_2, INITIAL_HOLDERS_AMOUNTS, SALT, DefaultTxInfoMock,
deploy_memecoin_through_factory, ETH_ADDRESS, deploy_memecoin_through_factory_with_owner,
JEDI_ROUTER_ADDRESS, MEMEFACTORY_ADDRESS, ALICE, BOB, pow_256, LOCK_MANAGER_ADDRESS,
deploy_and_launch_memecoin, TRANSFER_LIMIT_DELAY, UNLOCK_TIME, DEFAULT_MIN_LOCKTIME
deploy_and_launch_memecoin, TRANSFER_RESTRICTION_DELAY, UNLOCK_TIME, DEFAULT_MIN_LOCKTIME
};
use unruggable::token::interface::{
IUnruggableMemecoin, IUnruggableMemecoinDispatcher, IUnruggableMemecoinDispatcherTrait
Expand Down Expand Up @@ -255,7 +245,8 @@ mod memecoin_entrypoints {
// setting block timestamp >= launch_time + transfer_delay. Transfer should succeed
// as multi calls to the same recipient are allowed after the delay
start_warp(
CheatTarget::One(memecoin.contract_address), launch_timestamp + TRANSFER_LIMIT_DELAY
CheatTarget::One(memecoin.contract_address),
launch_timestamp + TRANSFER_RESTRICTION_DELAY
);
start_prank(CheatTarget::One(memecoin.contract_address), INITIAL_HOLDER_1());
let send_amount = memecoin.transfer_from(INITIAL_HOLDER_1(), ALICE(), 0);
Expand Down Expand Up @@ -313,7 +304,7 @@ mod memecoin_internals {
// create a unique address
let unique_recipient: ContractAddress = (index.into() + 9999).try_into().unwrap();

// creating and setting unique tx_hash here
// creating and setting unique tx_hash here
let mut tx_info: TxInfoMock = Default::default();
tx_info.transaction_hash = Option::Some(index.into() + 9999);
snforge_std::start_spoof(CheatTarget::One(memecoin.contract_address), tx_info);
Expand Down Expand Up @@ -348,7 +339,7 @@ mod memecoin_internals {
break;
}

// creating and setting unique tx_hash here
// creating and setting unique tx_hash here
let mut tx_info: TxInfoMock = Default::default();
tx_info.transaction_hash = Option::Some(index.into() + 9999);
snforge_std::start_spoof(CheatTarget::One(memecoin.contract_address), tx_info);
Expand Down Expand Up @@ -377,7 +368,7 @@ mod memecoin_internals {
// create a unique address
let unique_recipient: ContractAddress = (index.into() + 9999).try_into().unwrap();

// creating and setting unique tx_hash here
// creating and setting unique tx_hash here
let mut tx_info: TxInfoMock = Default::default();
tx_info.transaction_hash = Option::Some(index.into() + 9999);
snforge_std::start_spoof(CheatTarget::One(memecoin.contract_address), tx_info);
Expand All @@ -404,7 +395,7 @@ mod memecoin_internals {
// create a unique address
let unique_recipient: ContractAddress = (index.into() + 9999).try_into().unwrap();

// creating and setting unique tx_hash here
// creating and setting unique tx_hash here
let mut tx_info: TxInfoMock = Default::default();
tx_info.transaction_hash = Option::Some(index.into() + 9999);
snforge_std::start_spoof(CheatTarget::One(memecoin.contract_address), tx_info);
Expand Down
Loading

0 comments on commit 1323cfc

Please sign in to comment.