ButtonswapPair
Inherits: IButtonswapPair, ButtonswapERC20
State Variables
MINIMUM_LIQUIDITY
The smallest value that {IButtonswapERC20-totalSupply} can be.
After the first mint the total liquidity (represented by the liquidity token total supply) can never drop below this value. This is to protect against an attack where the attacker mints a very small amount of liquidity, and then donates pool tokens to skew the ratio. This results in future minters receiving no liquidity tokens when they deposit. By enforcing a minimum liquidity value this attack becomes prohibitively expensive to execute.
uint256 public constant MINIMUM_LIQUIDITY = 10 ** 3;
BPS
Denominator for basis points.
uint256 private constant BPS = 10_000;
movingAverageWindow
The duration for which the moving average is calculated for.
uint32 public movingAverageWindow;
maxVolatilityBps
Numerator (over 10_000) of the threshold when price volatility triggers maximum single-sided timelock duration.
uint16 public maxVolatilityBps;
minTimelockDuration
How long the minimum singled-sided timelock lasts for.
uint32 public minTimelockDuration;
maxTimelockDuration
How long the maximum singled-sided timelock lasts for.
uint32 public maxTimelockDuration;
maxSwappableReservoirLimitBps
Numerator (over 10_000) of the fraction of the pool balance that acts as the maximum limit on how much of the reservoir can be swapped in a given timeframe.
uint16 public maxSwappableReservoirLimitBps;
swappableReservoirGrowthWindow
How much time it takes for the swappable reservoir value to grow from nothing to its maximum value.
uint32 public swappableReservoirGrowthWindow;
factory
The address of the {ButtonswapFactory} instance used to create this Pair.
Set to msg.sender
in the Pair constructor.
address public immutable factory;
token0
The address of the first sorted token.
address public immutable token0;
token1
The address of the second sorted token.
address public immutable token1;
pool0Last
The active token0
liquidity amount following the last swap.
This value is used to determine active liquidity balances after potential rebases until the next future swap.
uint112 internal pool0Last;
pool1Last
The active token1
liquidity amount following the last swap.
This value is used to determine active liquidity balances after potential rebases until the next future swap.
uint112 internal pool1Last;
blockTimestampLast
The timestamp of the block that the last swap occurred in.
uint32 internal blockTimestampLast;
price0CumulativeLast
The time-weighted average price of the Pair.
The price is of token0
in terms of token1
.
The price is represented as a UQ112x112 to maintain precision.
Consequently this value must be divided by 2^112
to get the actual price.
Because of the time weighting, price0CumulativeLast
must also be divided by the total Pair lifetime to get the average price over that time period.
uint256 public price0CumulativeLast;
price1CumulativeLast
The time-weighted average price of the Pair.
The price is of token1
in terms of token0
.
The price is represented as a UQ112x112 to maintain precision.
Consequently this value must be divided by 2^112
to get the actual price.
Because of the time weighting, price1CumulativeLast
must also be divided by the total Pair lifetime to get the average price over that time period.
uint256 public price1CumulativeLast;
movingAveragePrice0Last
The value of movingAveragePrice0
at the time of the last swap.
uint256 internal movingAveragePrice0Last;
singleSidedTimelockDeadline
The timestamp for when the single-sided timelock concludes.
The timelock is initiated based on price volatility of swaps over the last movingAverageWindow
, and can be
extended by new swaps if they are sufficiently volatile.
The timelock protects against attempts to manipulate the price that is used to valuate the reservoir tokens during
single-sided operations.
It also guards against general legitimate volatility, as it is preferable to defer single-sided operations until
it is clearer what the market considers the price to be.
uint120 public singleSidedTimelockDeadline;
swappableReservoirLimitReachesMaxDeadline
The timestamp by which the amount of reservoir tokens that can be exchanged during a single-sided operation reaches its maximum value. This maximum value is not necessarily the entirety of the reservoir, instead being calculated as a fraction of the corresponding token's active liquidity.
uint120 public swappableReservoirLimitReachesMaxDeadline;
isPaused
Whether or not the pair is isPaused (paused = 1, unPaused = 0). When paused, all operations other than dual-sided burning LP tokens are disabled.
uint8 internal isPaused;
unlocked
Value to track the state of the re-entrancy guard.
uint8 private unlocked = 1;
Functions
lock
Guards against re-entrancy.
modifier lock();
singleSidedTimelock
Prevents certain operations from being executed if the price volatility induced timelock has yet to conclude.
modifier singleSidedTimelock();
checkPaused
Prevents operations from being executed if the Pair is currently paused.
modifier checkPaused();
sendOrRefundFee
Called whenever an LP wants to burn their LP tokens to make sure they get their fair share of fees.
If feeTo
is defined, balanceOf(address(this))
gets transferred to feeTo
.
If feeTo
is not defined, balanceOf(address(this))
gets burned and the LP tokens all grow in value.
modifier sendOrRefundFee();
onlyFactory
Prevents operations from being executed if the caller is not the factory.
modifier onlyFactory();
constructor
constructor();
name
Returns the name of the token.
function name() external view override(ButtonswapERC20, IButtonswapERC20) returns (string memory _name);
Returns
Name | Type | Description |
---|---|---|
_name | string | The token name |
symbol
Returns the symbol of the token, usually a shorter version of the name.
function symbol() external view override(ButtonswapERC20, IButtonswapERC20) returns (string memory _symbol);
Returns
Name | Type | Description |
---|---|---|
_symbol | string | The token symbol |
_mintFee
Always mints liquidity equivalent to 1/6th of the growth in sqrt(k) and allocates to address(this)
If there isn't a feeTo
address defined, these LP tokens will get burned this 1/6th gets reallocated to LPs
function _mintFee(uint256 pool0, uint256 pool1, uint256 pool0New, uint256 pool1New) internal;
Parameters
Name | Type | Description |
---|---|---|
pool0 | uint256 | The token0 active liquidity balance at the start of the ongoing swap |
pool1 | uint256 | The token1 active liquidity balance at the start of the ongoing swap |
pool0New | uint256 | The token0 active liquidity balance at the end of the ongoing swap |
pool1New | uint256 | The token1 active liquidity balance at the end of the ongoing swap |
_updatePriceCumulative
Updates price0CumulativeLast
and price1CumulativeLast
based on the current timestamp.
function _updatePriceCumulative(uint256 pool0, uint256 pool1) internal;
Parameters
Name | Type | Description |
---|---|---|
pool0 | uint256 | The token0 active liquidity balance at the start of the ongoing swap |
pool1 | uint256 | The token1 active liquidity balance at the start of the ongoing swap |
_closestBound
Refer to closest-bound-math.md for more detail.
function _closestBound(uint256 poolALower, uint256 poolB, uint256 _poolALast, uint256 _poolBLast)
internal
pure
returns (uint256 closestBound);
Parameters
Name | Type | Description |
---|---|---|
poolALower | uint256 | The lower bound for the active liquidity balance of the non-fixed token |
poolB | uint256 | The active liquidity balance of the fixed token |
_poolALast | uint256 | The active liquidity balance at the end of the last swap for the non-fixed token |
_poolBLast | uint256 | The active liquidity balance at the end of the last swap for the fixed token |
Returns
Name | Type | Description |
---|---|---|
closestBound | uint256 | The bound for the active liquidity balance of the non-fixed token that produces a price ratio closest to last swap price |
_getLiquidityBalances
Refer to liquidity-balances-math.md for more detail.
function _getLiquidityBalances(uint256 total0, uint256 total1) internal view returns (LiquidityBalances memory lb);
Parameters
Name | Type | Description |
---|---|---|
total0 | uint256 | The total amount of token0 held by the Pair |
total1 | uint256 | The total amount of token1 held by the Pair |
Returns
Name | Type | Description |
---|---|---|
lb | LiquidityBalances | The current active and inactive liquidity balances |
_updateSingleSidedTimelock
Calculates current price volatility and initiates a timelock scaled to the volatility size. This timelock prohibits single-sided operations from being executed until enough time has passed for the timelock to conclude. This protects against attempts to manipulate the price that the reservoir is valued at during single-sided operations.
function _updateSingleSidedTimelock(uint256 _movingAveragePrice0, uint112 pool0New, uint112 pool1New) internal;
Parameters
Name | Type | Description |
---|---|---|
_movingAveragePrice0 | uint256 | The current movingAveragePrice0 value |
pool0New | uint112 | The token0 active liquidity balance at the end of the ongoing swap |
pool1New | uint112 | The token1 active liquidity balance at the end of the ongoing swap |
_getSwappableReservoirLimit
Calculates the current limit on the number of reservoir tokens that can be exchanged during a single-sided operation. This is based on corresponding active liquidity size and time since and size of the last single-sided operation.
function _getSwappableReservoirLimit(uint256 poolA) internal view returns (uint256 swappableReservoir);
Parameters
Name | Type | Description |
---|---|---|
poolA | uint256 | The active liquidity balance for the non-zero reservoir token |
Returns
Name | Type | Description |
---|---|---|
swappableReservoir | uint256 | The amount of non-zero reservoir token that can be exchanged as part of a single-sided operation |
getSwappableReservoirLimit
Returns the current limit on the number of reservoir tokens that can be exchanged during a single-sided mint/burn operation.
function getSwappableReservoirLimit() external view returns (uint256 swappableReservoirLimit);
Returns
Name | Type | Description |
---|---|---|
swappableReservoirLimit | uint256 | The amount of reservoir token that can be exchanged |
_updateSwappableReservoirDeadline
Updates the value of swappableReservoirLimitReachesMaxDeadline
which is the time at which the maximum
amount of inactive liquidity tokens can be exchanged during a single-sided operation.
Assumes swappedAmountA
is less than or equal to maxSwappableReservoirLimit
function _updateSwappableReservoirDeadline(uint256 poolA, uint256 swappedAmountA) internal;
Parameters
Name | Type | Description |
---|---|---|
poolA | uint256 | The active liquidity balance for the non-zero reservoir token |
swappedAmountA | uint256 | The amount of non-zero reservoir tokens that were exchanged during the ongoing single-sided operation |
getIsPaused
Whether the Pair is currently paused
function getIsPaused() external view returns (bool _isPaused);
Returns
Name | Type | Description |
---|---|---|
_isPaused | bool | The paused state |
setIsPaused
Updates the pause state. This can only be called by the Factory address.
function setIsPaused(bool isPausedNew) external onlyFactory;
Parameters
Name | Type | Description |
---|---|---|
isPausedNew | bool | The new value for isPaused |
getLiquidityBalances
Get the current liquidity values.
function getLiquidityBalances()
external
view
returns (uint112 _pool0, uint112 _pool1, uint112 _reservoir0, uint112 _reservoir1, uint32 _blockTimestampLast);
Returns
Name | Type | Description |
---|---|---|
_pool0 | uint112 | The active token0 liquidity |
_pool1 | uint112 | The active token1 liquidity |
_reservoir0 | uint112 | The inactive token0 liquidity |
_reservoir1 | uint112 | The inactive token1 liquidity |
_blockTimestampLast | uint32 | The timestamp of when the price was last updated |
movingAveragePrice0
The current movingAveragePrice0
value, based on the current block timestamp.
This is the token0
price, time weighted to prevent manipulation.
Refer to reservoir-valuation.md for more detail.
The price is represented as a UQ112x112 to maintain precision.
It is used to valuate the reservoir tokens that are exchanged during single-sided operations.
function movingAveragePrice0() public view returns (uint256 _movingAveragePrice0);
Returns
Name | Type | Description |
---|---|---|
_movingAveragePrice0 | uint256 | The current movingAveragePrice0 value |
mint
Mints new liquidity tokens to to
based on amountIn0
of token0
and amountIn1 of
token1` deposited.
Expects both tokens to be deposited in a ratio that matches the current Pair price.
The token deposits are deduced to be the delta between token balance before and after the transfers in order to account for unusual tokens. Refer to mint-math.md for more detail.
function mint(uint256 amountIn0, uint256 amountIn1, address to)
external
lock
checkPaused
sendOrRefundFee
returns (uint256 liquidityOut);
Parameters
Name | Type | Description |
---|---|---|
amountIn0 | uint256 | The amount of token0 that should be transferred in from the user |
amountIn1 | uint256 | The amount of token1 that should be transferred in from the user |
to | address | The account that receives the newly minted liquidity tokens |
Returns
Name | Type | Description |
---|---|---|
liquidityOut | uint256 | THe amount of liquidity tokens minted |
mintWithReservoir
Mints new liquidity tokens to to
based on how much token0
or token1
has been deposited.
The token transferred is the one that the Pair does not have a non-zero inactive liquidity balance for.
Expects only one token to be deposited, so that it can be paired with the other token's inactive liquidity.
The token deposits are deduced to be the delta between token balance before and after the transfers in order to account for unusual tokens. Refer to mint-math.md for more detail.
function mintWithReservoir(uint256 amountIn, address to)
external
lock
checkPaused
singleSidedTimelock
sendOrRefundFee
returns (uint256 liquidityOut);
Parameters
Name | Type | Description |
---|---|---|
amountIn | uint256 | The amount of tokens that should be transferred in from the user |
to | address | The account that receives the newly minted liquidity tokens |
Returns
Name | Type | Description |
---|---|---|
liquidityOut | uint256 | THe amount of liquidity tokens minted |
burn
Burns liquidityIn
liquidity tokens to redeem to to
the corresponding amountOut0
of token0
and amountOut1
of token1
.
Refer to burn-math.md for more detail.
function burn(uint256 liquidityIn, address to)
external
lock
sendOrRefundFee
returns (uint256 amountOut0, uint256 amountOut1);
Parameters
Name | Type | Description |
---|---|---|
liquidityIn | uint256 | The amount of liquidity tokens to burn |
to | address | The account that receives the redeemed tokens |
Returns
Name | Type | Description |
---|---|---|
amountOut0 | uint256 | The amount of token0 that the liquidity tokens are redeemed for |
amountOut1 | uint256 | The amount of token1 that the liquidity tokens are redeemed for |
burnFromReservoir
Burns liquidityIn
liquidity tokens to redeem to to
the corresponding amountOut0
of token0
and amountOut1
of token1
.
Only returns tokens from the non-zero inactive liquidity balance, meaning one of amountOut0
and amountOut1
will be zero.
Refer to burn-math.md for more detail.
function burnFromReservoir(uint256 liquidityIn, address to)
external
lock
checkPaused
singleSidedTimelock
sendOrRefundFee
returns (uint256 amountOut0, uint256 amountOut1);
Parameters
Name | Type | Description |
---|---|---|
liquidityIn | uint256 | The amount of liquidity tokens to burn |
to | address | The account that receives the redeemed tokens |
Returns
Name | Type | Description |
---|---|---|
amountOut0 | uint256 | The amount of token0 that the liquidity tokens are redeemed for |
amountOut1 | uint256 | The amount of token1 that the liquidity tokens are redeemed for |
swap
Swaps one token for the other, taking amountIn0
of token0
and amountIn1
of token1
from the sender and sending amountOut0
of token0
and amountOut1
of token1
to to
.
The price of the swap is determined by maintaining the "K Invariant".
A 0.3% fee is collected to distribute between liquidity providers and the protocol.
The token deposits are deduced to be the delta between the current Pair contract token balances and the last stored balances.
Optional calldata can be passed to data
, which will be used to confirm the output token transfer with to
if to
is a contract that implements the {IButtonswapCallee} interface.
Refer to swap-math.md for more detail.
function swap(uint256 amountIn0, uint256 amountIn1, uint256 amountOut0, uint256 amountOut1, address to)
external
lock
checkPaused;
Parameters
Name | Type | Description |
---|---|---|
amountIn0 | uint256 | The amount of token0 that the sender sends |
amountIn1 | uint256 | The amount of token1 that the sender sends |
amountOut0 | uint256 | The amount of token0 that the recipient receives |
amountOut1 | uint256 | The amount of token1 that the recipient receives |
to | address | The account that receives the swap output |
setMovingAverageWindow
Updates the movingAverageWindow parameter of the pair. This can only be called by the Factory address. Refer to parameters.md for more detail.
function setMovingAverageWindow(uint32 newMovingAverageWindow) external onlyFactory;
Parameters
Name | Type | Description |
---|---|---|
newMovingAverageWindow | uint32 | The new value for movingAverageWindow |
setMaxVolatilityBps
Updates the maxVolatilityBps parameter of the pair. This can only be called by the Factory address. Refer to parameters.md for more detail.
function setMaxVolatilityBps(uint16 newMaxVolatilityBps) external onlyFactory;
Parameters
Name | Type | Description |
---|---|---|
newMaxVolatilityBps | uint16 | The new value for maxVolatilityBps |
setMinTimelockDuration
Updates the minTimelockDuration parameter of the pair. This can only be called by the Factory address. Refer to parameters.md for more detail.
function setMinTimelockDuration(uint32 newMinTimelockDuration) external onlyFactory;
Parameters
Name | Type | Description |
---|---|---|
newMinTimelockDuration | uint32 | The new value for minTimelockDuration |
setMaxTimelockDuration
Updates the maxTimelockDuration parameter of the pair. This can only be called by the Factory address. Refer to parameters.md for more detail.
function setMaxTimelockDuration(uint32 newMaxTimelockDuration) external onlyFactory;
Parameters
Name | Type | Description |
---|---|---|
newMaxTimelockDuration | uint32 | The new value for maxTimelockDuration |
setMaxSwappableReservoirLimitBps
Updates the maxSwappableReservoirLimitBps parameter of the pair. This can only be called by the Factory address. Refer to parameters.md for more detail.
function setMaxSwappableReservoirLimitBps(uint16 newMaxSwappableReservoirLimitBps) external onlyFactory;
Parameters
Name | Type | Description |
---|---|---|
newMaxSwappableReservoirLimitBps | uint16 | The new value for maxSwappableReservoirLimitBps |
setSwappableReservoirGrowthWindow
Updates the swappableReservoirGrowthWindow parameter of the pair. This can only be called by the Factory address. Refer to parameters.md for more detail.
function setSwappableReservoirGrowthWindow(uint32 newSwappableReservoirGrowthWindow) external onlyFactory;
Parameters
Name | Type | Description |
---|---|---|
newSwappableReservoirGrowthWindow | uint32 | The new value for swappableReservoirGrowthWindow |
Structs
LiquidityBalances
A set of liquidity values.
struct LiquidityBalances {
uint256 pool0;
uint256 pool1;
uint256 reservoir0;
uint256 reservoir1;
}