Factory is a utility contract used by front application and other contracts to get the code of a pool contract or a farm contract.
get_pool_code(token1_address, token2_address, pool_address, lp_token_address, state_address)
Return the code to create a pool for a pair of tokens.
token1_address
is the first token address of the pairtoken2_address
is the second token address of the pairpool_address
is the genesis address of the pool chainlp_token_address
is the address of the lp token (it should be the creation address of the pool)state_address
is the address holding the state of a pool (will be soon removed)
get_farm_code(lp_token, start_date, end_date, reward_token, farm_genesis_address)
Return the code to create a farm for a LP token and a reward token.
lp_token
is the lp token to provide in the farmstart_date
is the timestamp (in sec) where the farm starts to give reward (should be between 2 hours and 1 week from farm creation date)end_date
is the timestamp (in sec) where the farm ends to give reward (should be between 1 month and 1 year from start date)reward_token
is the reward token address or "UCO"farm_genesis_address
is the genesis address of the farm contract chain
get_lp_token_definition(token1_address, token2_address)
Return the lp token definition to use when creating a pool. Returns a JSON stringified
token1_address
is the address of the first tokentoken2_address
is the address of the second token
Pool is the main contract of the AMM model. It hold the liquidity of a pair of token and expose all functionnality to add / remove liquidity and swap.
get_pool_infos()
Returns infos of the pool as:
{
"token1": {
"address": "00001234...",
"reserve": 1021.45
},
"token2": {
"address": "00005678...",
"reserve": 894.565
},
"lp_token": {
"address": "0000ABCD...",
"supply": 950.45645
},
"fee": 0.25,
"protocol_fee": 0.25,
"stats": {
"token1_total_fee": 0.025,
"token1_total_protocol_fee": 0.025,
"token1_total_volume": 10,
"token2_total_fee": 0.075,
"token2_total_protocol_fee": 0.075,
"token2_total_volume": 30
}
}
In next function, token1 and token2 represent the one returned by this function
get_equivalent_amount(token_address, amount)
Returns the equivalent amount of the other token of the pool. This should be used in the process of adding liquidity
token_address
is the token you want to provide (result amount will be the other token)amount
is the amount of token_address you want to provide
get_ratio(token_address)
Returns the pool ratio
token_address
is the token you want to provide (result amount will be the other token)
get_lp_token_to_mint(token1_amount, token2_amount)
Returns the amount of LP token that will be minted if the amount of tokens are provided
token1_amount
Amount of token1 to providetoken2_amount
Amount of token2 to provide
get_output_swap_infos(token_address, input_amount)
Returns the info about a swap: expected output_amount, fee and price impact
token_address
One of the 2 tokens of the poolinput_amount
Amount of this token you want to swap
{ "fee": 0.006, "protocol_fee": 0.003, "output_amount": 1.48073705, "price_impact": 0.997 }
get_input_swap_infos(token_address, output_amount)
Returns the info about a swap: expected input_amount, fee and price impact
token_address
One of the 2 tokens of the pooloutput_amount
Amount of this token swapped
{ "fee": 0.006, "protocol_fee": 0.003, "input_amount": 1.48073705, "price_impact": 0.997 }
get_remove_amounts(lp_token_amount)
Returns amounts of token to get back when removing liquidity
lp_token_amount
Number of lp token to remove
{ "token1": 11.662465, "token2": 8.54834787 }
add_liquidity(token1_min_amount, token2_min_amount)
This action allow user to add liquidity to the pool. User must send tokens to the pool's genesis address. The amounts sent should be equivalent to the pool ratio. User can specify a slippage tolerance by providing the minimum amount by token that the pool can use. If there is more fund sent by the user than the needed liquidity, the excedent is returned to the user. In exchange of the liquidity, the user will receive some LP token.
token1_min_amount
is the minimum amount of token1 to add in liquiditytoken2_min_amount
is the minimum amount of token2 to add in liquidity
remove_liquidity()
This action allow user to remove the liquidity he previously provided. User must send the lp token he wants to remove to the burn address ("000...000") (don't forget to add the pool in recipient otherwise lp token will only be burned). The pool will calculate the share of the user and return the corresponding amount of both pool tokens.
swap(min_to_receive)
This action allow user to swap a token of the pool against the other token. User must send the input token to the pool's genesis address. The pool will calculate the output amount and send it to the user. User can specify a slippage tolerance by providing the minimum amount of the output token to receive.
min_to_receive
is the minimum amount of the output token to receive
update_code()
This action can be triggered only by the Router contract of the dex. It allow the Router to request the pool to update it's code. The pool will request the new code using the function get_pool_code
of the Factory (see above).
set_protocol_fee(new_protocol_fee)
This action can be triggered only by the Master chain of the dex. It allow to update the protocol fee of the pool.
Farm is a contract allowing users to deposit lp token from a pool and to receive reward for a period of time.
get_farm_infos()
Returns the informations of the farm
{
"lp_token_address": "0000ABCD...",
"reward_token": "00001234...", // or "UCO"
"start_date": 1705500842,
"end_date": 1705912842,
"remaining_reward": 123456.789,
"lp_token_deposited": 456123.987235,
"nb_deposit": 132,
"stats": {
"reward_distributed": 1234.65657
}
}
get_user_infos(user_genesis_address)
Returns the informations of a user who has deposited lp token in the farm
{
"deposited_amount": 456123.789456,
"reward_amount": 12.456339
}
deposit()
This action allow user to deposit lp token in the farm. User must send tokens to the farm's genesis address. It's fund will be hold by the contract and could be reclaimed using withdraw
action. The user will gain reward each second based on the reward amount and it's share of the farm. The reward can be claimed using the claim
actions.
A user can deposit multiple time in the same farm, or in multiple farms.
claim()
This action allow user to claim all the reward he earned since he deposited in the farm or since it's last claim.
withdraw(amount)
This action allow user to withdraw all or a part of it's deposited lp token. In the same time is also claim it's earned rewards.
amount
is the amount the user wants to withdraw
udpate_dates(new_start_date, new_end_date)
This action can be triggered only by the Master address of the dex. The farm will update the start and end date.
update_code()
This action can be triggered only by the Router contract of the dex. It allow the Router to request the farm to update it's code. The farm will request the new code using the function get_farm_code
of the Factory (see above).
This farm allows users to lock their LP tokens for a given time in order to receive rewards.
get_farm_infos()
Returns the informations of the farm
{
"lp_token_address": "0000ABCD...", // LP Token Address
"reward_token": "00001234...", // Reward token address or "UCO"
"start_date": 1705500842, // Unix timestamp
"end_date": 1705912842, // Unix timestamp
"remaining_reward": 123456.789, // Amount of rewards remaining
"rewards_distributed": 4523.97235, // Amount of rewards already distributed
"available_levels": { // an enumeration (string (level) ⇒ end date)
"1": 1750829615,
// ...
},
"stats": {
"1": {
"weight": 0.013, // Weight of this level
"deposits_count": 1344.454, // Current count of deposits on this level
"lp_tokens_deposited": 34553, // Current amount deposited on this level
"remaining_rewards": 3564332.333, // Remaining rewards for this level (based on current distribution)
},
// ...
}
}
get_user_infos(user_genesis_address)
Returns the deposits' details of a given user.
[
{
"id": "1725136117", // Deposit's identifier
"amount": 1213.456339, // Amount locked
"reward_amount": 33.45, // Current rewards accumulated
"start": 1750829615, // Timestamp lock begin
"end": 1782365634, // Timestamp lock end
"level": "3", // Current level
},
// ...
]
deposit(level :: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "max")
level
: Determine the lock duration
This action allow users to deposit LP tokens in the farm. Users must send LP tokens to the farm's genesis address. Users may deposit multiple times. Deposits may be merged together for optimisation.
note: max
can be used when there is less than 3 years remaining to ensure the lock ends with the farm's end.
claim(identifier :: string)
identifier
: Deposit's identifier
This action allow users to claim a single deposit's rewards. The LP tokens remains in the deposit. The deposit must be unlocked.
withdraw(amount :: float, identifier :: string)
amount
: Amount of LP tokens to withdrawidentifier
: Deposit's identifier
This action allow users to withdraw partially or entirely a deposit. The deposit must be unlocked.
relock(level :: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "max", identifier :: string)
level
: Determine the lock durationidentifier
: Deposit's identifier
This action allow users to update a deposit. It can only expand the lock duration. Accumulated rewards are transferred to the user.
note: max
can be used when there is less than 3 years remaining to ensure the lock ends with the farm's end.
update_code()
This action can be triggered only by the Router contract of the dex. It allow the Router to request the farm to update it's code. The farm will request the new code using the function get_farm_code
of the Factory (see above).
Router is a helper contract for user to easily retrieve existing pools and create new pools.
get_pool_addresses(token1_address, token2_address)
Returns the info of the pool for the 2 tokens address.
token1_address
is the address of the first tokentoken2_address
is the address of the second token
{
"address": "00001234...",
"lp_token_address": "00005678..."
}
get_pool_list()
Return the infos of all the pools. tokens
field is the address of both token concatenated and separated by a slash.
[
{
"address": "00001234...",
"lp_token_address": "00005678...",
"tokens": "0000456.../000789..."
}
]
get_farm_list()
Return the infos of all the farms.
{
"lp_token_address": "00001234...",
"start_date": 1705500842,
"end_date": 1705912842,
"reward_token": "00005678...", // or "UCO"
"address": "0000ABCD..."
}
add_pool(token1_address, token2_address, pool_creation_address)
This action allows users to add a new pool in the router. The transaction triggering this action should also add the first liquidity to a previously created pool. The transaction that created the pool should be a token transaction with the token definition returned by the function get_lp_token_definition
. It should also have the code returned by the function get_pool_code
.
add_farm(lp_token, start_date, end_date, reward_token, farm_creation_address)
This action allows the Master chain of the dex to add a new farm in the router. The transaction triggering this action should also add the first amount of reward token to the previously created farm. The transaction that created the farm should be a contract transaction with the code returned by the function get_farm_code
of the Factory contract.
update_code(new_code)
This action can be triggered only by the Master chain of the dex. It's allowing to update the code of the Router.
update_pools_code()
This action can be triggered only by the Master chain of the dex. It's allowing to update all the pools code. The Router will call the action update_code()
of all the known pool.
update_farms_code()
This action can be triggered only by the Master chain of the dex. It's allowing to update all the farms code. The Router will call the action update_code()
of all the known farm.
To get some statistics about the DEX, pool contracts are storing the volume and fee for both tokens since its creation. Farm contract also stores the reward already distibuted. You can refer to get_pool_infos
function and get_farm_infos
.
Those stats are accumulator since contract creation. For example, if you want to get the fee since the last 24h you have to retrieve the contract address of the pool 24h hour before (you can use node's getTransactionChain
graphql api with from
args) and call the function get_pool_infos
on this transaction address. Do the same for the current address and you can calculate the difference between both values. The difference is the fee paid since the last 24h
In the directory contracts you can find a script dex.js. This script provide the main functionnality to deploy the dex and test it.
node dex --help
dex [command]
Commands:
dex init_keychain Initialize the dex keychain with the primary services
dex deploy_factory Deploy the factory
dex deploy_router Deploy the router
dex update_router Update the router
dex update_pools Update all pool code
dex update_farms Update all farm code
dex update_protocol_fee Update the protocol fee for a pool
dex update_farm_dates Update the start and end date of a farm
dex create_tokens Create tokens and send them to user address
dex deploy_pool Deploy a pool for the token specified
dex add_liquidity Add liquidity to a pool
dex remove_liquidity Remove liquidity from a pool
dex swap Swap exact token for token
dex deploy_farm Deploy a farm for a lp token and a reward token
dex deposit Deposit LP Token in a farm
dex claim Claim token from a farming pool
dex withdraw Withdraw LP token from a farming pool and claim rewards
For each command you can get the help:
node dex swap --help
dex swap
Swap exact token for token
Options:
--token1 First token name (token to send) [string] [required]
--token2 Second token name (token to receive) [string] [required]
--token1_amount Amount of token to send [required]
--slippage Slippage in percentage (2 = 2%) to apply. Default 2
To deploy the main dex contract you have to init the keychain and deploy the router:
node dex init_keychain
node dex deploy_factory
node dex deploy_router
NB: Don't forget to faucet the Master genesis address before executing node dex deploy_factory
To test the dex you first have to create some tokens, it will create tokens with 1 million supply
node dex create_tokens --number 6
This will create multiple tokens with the name token0, token1, token2 ...
Then you can deploy a pool:
node dex deploy_pool --token1 token3 --token2 token4 --token1_amount 100 --token2_amount 200
Then you can use script to add / remove liquidity or swap:
node dex add_liquidity --token1 token3 --token1_amount 750 --token2 token4
node dex swap --token1 token3 --token1_amount 50 --token2 token4
node dex remove_liquidity --token1 token3 --token2 token4 --lp_token_amount 72
You can also deploy a farm (Master address should have the reward tokens):
node dex deploy_farm --lp_token 0000e866...f160 --reward_token token4 --reward_token_amount 2000 --farm_type 1
Then you can use script to deposit, claim or withdraw:
node dex deposit --lp_token 0000e866...f160 --reward_token UCO --lp_token_amount 20
node dex claim --lp_token 0000e866...f160 --reward_token UCO
node dex withdraw --lp_token 0000e866...f160 --reward_token UCO --amount 20
To update router code you can use this script:
node dex update_router
To update pools code you can use this script:
node dex deploy_factory
node dex update_pools
To update farms code you can use this script:
node dex deploy_factory
node dex update_farms
- Security access with your Archethic Wallet
- Flutter 3.19+
- Dart 3.3+
*** This Application is currently in active development so it might fail to build. Please refer to issues or create new issues if you find any. Contributions are welcomed.