Squid Swap is a decentralized exchange platform designed to expand the utility and functionality of the Squid token ecosystem.

SquidSwap is a decentralized finance (DeFi) platform with a decentralized exchange (DEX) and passive income-generating services such as staking, liquidity pools, and yield farming in its ecosystem.
Squid Swap is expected to launch in May 20213 and is a fork of Squid, a popular DEX, which itself is a fork of Uniswap, the world's leading DEX by trading volume. But unlike its competitors, Squid Swap's core purpose is mainly to increase the utility of Squid tokens.
Some of the design decisions behind the Squidswap v2 core contract. It covers new features of the contract, including arbitrary pairing between ERC20s, enhanced price oracles that allow other contracts to estimate the time-weighted average price over a given time interval, "flash swaps" that allow traders to receive assets before paying later in a trade and use them elsewhere, and protocol fees that can be enabled in the future. It also redesigned the contract to reduce its attack surface.
The mechanics of the Squidswap v2 “core” contracts, including the pairing contract that stores liquidity provider funds and the factory contract used to instantiate the pairing contract.
1 Introduction Squidswap v1 is a smart contract on-chain system on the Bscscan blockchain that implements an automatic liquidity protocol based on the "constant product formula" [1].
Each Squidswap v1 pair stores the pooled reserves of both assets and provides liquidity for both assets, keeping the product of the reserves constant and non-decreasing. Traders pay a 30 basis point fee when trading, which is paid by the liquidity provider. The contract is not upgradeable. Squidswap v2 is a new implementation based on the same formula with several highly desirable new features. Most importantly, it allows the creation of arbitrary ERC20/ERC20 pairs, rather than just supporting pairs between ERC20 and BNB. It also provides a hardened price oracle that accumulates the relative price of the two assets at the beginning of each block. This allows other contracts on Bscscan to estimate the time-weighted average price of the two assets over arbitrary time intervals.
Finally, it enables “flash swaps” where users can freely receive assets and use them elsewhere on-chain, simply paying (or returning) those assets at the end of the transaction. While contracts are generally not upgradeable, there is a private key that updates a variable on the factory contract to enable a 5 basis point transaction fee on-chain. This fee will initially be removed, but may be removed in the future, after which liquidity providers will receive 25 basis points per trade instead of 30 basis points. As described in Section 3, Squidswap v2 also fixes some minor issues in Squidswap v1, as well as reorganizing the implementation, reducing Squidswap’s attack surface, and making the system easier to upgrade by minimizing the logic in the “core” contract that holds liquidity provider funds.
In fact, using Squidswap v2 requires calling the pairing contract through the "router" contract, which calculates the transaction or deposit amount and transfers the funds to the pairing contract. 2 New Features 2.1 ERC-20 Pairs Squidswap v1 uses ETH as a bridge currency.
Each pair has ETH as one of its assets. This makes every trade between ABC and XYZ go through the ETH/ABC pair and the BNB/XYZ pair, streamlining the process and reducing liquidity fragmentation.
However, this rule imposes significant costs on liquidity providers. All liquidity providers have BNB exposure and suffer temporary losses due to price changes of other assets relative to BNB.
For example, when two assets, ABC and XYZ, are correlated, if they are both USD stablecoin liquidity providers on Squidswap pairs, ABC/XYZ will generally suffer less short-term losses than ABC/BNB or XYZ/BNB pairs. Using BNB as a mandatory bridge currency also imposes costs on traders.
Traders have to pay twice as much in fees as a straight ABC/XYZ pair, and they suffer double the slippage. Squidswap v2 allows liquidity providers to create pairing contracts for any two ERC-20s.
The proliferation of pairings between arbitrary ERC-20s may make it more difficult to find the best path to trade a specific pairing, but routing can be handled at a higher layer (either off-chain or via on-chain routers or aggregators).
2.2 Price Prediction The marginal price offered by Squidswap at time t (excluding fees) can be calculated by dividing the reserves of asset a by the reserves of asset b. pt = r a t r b t (1) Since arbitrageurs will trade with Squidswap if this price is incorrect (by a sufficient amount to cover fees), the price offered by Squidswap tends to track the relative market price of the assets, as shown by Angris et al. [2].
This means it can be used as an approximate price oracle. However, Squidswap v1 is not safe to use as an on-chain price oracle because it is very easy to manipulate. Suppose some other contract uses the current BNB-USDT price to settle derivatives.
An attacker who wants to manipulate the measured price could buy BNB from the BNB-USDT pair, trigger the settlement of the derivatives contract (causing it to settle based on an artificially inflated price), and then sell the BNB back into the pair to trade it back to the true price. 1 This can even be done as an atomic transaction, or by a miner who controls the order of transactions within a block. Squidswap v2 improves on the oracle’s functionality by measuring and recording the price before the first transaction in each block (or, equivalently, after the last transaction in the block). This price is harder to manipulate than the price within a block. If an attacker submits a transaction that attempts to manipulate the price at the end of a block, other arbitrageurs may submit another transaction in the same block to trade immediately. Miners (or attackers who fill up an entire block with enough gas) can manipulate the price at the end of a block, but they may not have a particular advantage in arbitrage trading unless they also mine the next block. Specifically, Squidswap v2 accumulates this price by tracking the cumulative sum of prices at the start of each block where someone interacts with the contract. Each price is weighted by the amount of time that has passed since the last block was updated, based on the block timestamp. 2 This means that the accumulated value at any given time (after update) should be the sum of the spot prices for every second in the contract’s history. at = Xt i = 1 pi (2) To estimate the time-weighted average price from time t1 to t2, an external caller can check the value of the accumulator at t1 and then again at t2, subtract the first value from the second, and divide by the number of seconds that have passed. (Note that the contract itself does not store the historical values of this accumulator; the caller must call the contract at the beginning of the period to read and store this value.) pt1,t2 = Pt2 i = t1 pi t2−t1 = Pt2 i = 1 pi−pt1 i = 1 pi t2−t1 = at2−at1 t2−t1 (3) The oracle user can choose when to start and end this period. Choosing a longer period makes it more expensive for an attacker to manipulate TWAP, even though it will result in lower prices. A complication is this: should we measure the price of asset A by asset B, or should we measure the price of asset B by asset A? Although the spot price of A relative to B is always the inverse of the spot price of B relative to A, the average price of asset A relative to asset B over a specific time period is not equal to the average price of asset B relative to asset A.The inverse of the average price of 3. For example, if the USDT/BNB price in block 1 is 100 and the USDT/BNB price in block 2 is 300, the average USDT/BNB price will be 1/150 USDT/BNB. Since the contract has no way of knowing which of the two assets the user wishes to use as the unit of account, Squidswap v2 tracks both prices.
Another complication is that someone could send assets to the pairing contract, changing its balance and marginal price, without interacting with it and thus without triggering an oracle update. If the contract simply checks its own balance and updates the oracle based on the current price, an attacker could send assets to the contract immediately before it is called for the first time in a block, thereby manipulating the oracle. If the last transaction was in a block with a timestamp of X seconds ago, the contract will incorrectly multiply the new price by X and then add it up, even though no one has 2 Because miners have some freedom to set block timestamps, users of the oracle should be aware that these values may not correspond exactly to real-world time. 3 The arithmetic mean price of asset A relative to asset B over a given period is equal to the reciprocal of the harmonic mean price of asset B relative to asset A over that period. If the contract measures the geometric mean price, then the prices are the reciprocals of each other. However, the geometric mean TWAP is less commonly used and difficult to calculate on Squidswap. There is a chance to trade at this price.
To prevent this, the core contract caches its reserves after each interaction and updates the oracle with prices derived from the cached reserves instead of the current reserves. In addition to protecting the oracle from manipulation, this change also enables the contract re-architecting described in Section 3.2 below. 2.2.1 Precision Since Solidity does not have first-class support for non-integer numeric data types, Squidswap v2 uses a simple binary fixed-point format to encode and manipulate prices. Specifically, prices at a given moment are stored as UQ112.112 numbers, which means that 112 fractional bits of precision are specified on both sides of the decimal point, and there is no sign. These numbers have a range of [0, 2112−1]4 and a precision of 1 2 112. The UQ112.112 format was chosen for practical reasons - since these numbers can be stored in a uint24, which leaves 32 bits of the 256-bit storage slot free. It is also the case that each reserve stored in a uint112 also leaves 32 bits free in the (packed) 256-bit storage slot. This free space is used for the accumulation process described above. Specifically, the reserve is stored along with the timestamp of the most recent block in which at least one transaction occurred, modified by 2³² to make it fit in 32 bits. Furthermore, while the price at any given moment (stored as a UQ112.112 number) is guaranteed to fit in 2³²4 bits, the accumulation of this price over time is not. The extra 32 bits at the end of the A/B and B/A cumulative price storage slots are used to store overflow bits resulting from repeated additions of prices. This design means that price predictions only add an extra three SSTORE operations (currently costing about 15,000 gas) to the first transaction in each block. The main disadvantage is that 32 bits are not enough to store a timestamp value that can reasonably never overflow. In fact, Unix timestamp overflows
The date in uint32 is 02/07/2106. To ensure that the system continues to operate properly after that date and every multiple of 232−1 seconds thereafter, the oracle only needs to check the price at least once every certain period of time (approximately 136 years). This is because the core method of accumulation (and modification of timestamps) is actually overflow-safe, meaning that if the oracle uses an appropriate (simple) overflow algorithm to calculate the delta, transactions in the overflow interval can be properly accounted for. 2.3 Flash Swaps In Squidswap v1, a user who bought ABC with XYZ was required to send XYZ to the contract before receiving ABC. This is inconvenient if the user needs the ABC they bought to get the XYZ they paid. For example, the user might use that ABC to buy XYZ in some other contract to arbitrage the difference from Squidswap, or they might unwind a position on Maker or Compound by selling collateral to repay Squidswap. Squidswap v2 adds a new feature that allows users to receive and use assets before paying for them, as long as they make the payment in the same atomic transaction. The swap function calls an optional user-specified callback contract between transferring out the user-requested tokens and enforcing the invariant. After the callback completes, the contract checks the new balance and confirms that the invariant satisfies 4. The theoretical upper limit 2112−(1 2112) does not apply in this setting because UQ112.112 numbers in Squidswap are always generated by the ratio of two uint112s. The maximum ratio is 2 112−1 1=2112−1 (after adjusting for fees based on the amount paid).
If the contract does not have sufficient funds, it will revert the entire transaction. Users can also repay the Squidswap pool with the same tokens instead of completing the swap. This is effectively the equivalent of letting anyone quickly borrow any asset stored in the Uniswap pool (for a fee of the same 0.30% as Squidswap transaction fees). 5 2.4 Protocol Fee Squidswapv2 includes a 0.05% protocol fee that can be turned on and off. If turned on, this fee is sent to the feeTo address specified in the factory contract. Initially, no feeTo is set and no fees are charged. A pre-specified address feeToSetter can call the setFeeTo function on the Squidswap v2 factory contract to set feeTo to a different value. The feeToSetter can also call setFeeToSetter to change the feeToSeter address itself. If the feeTo address is set, the protocol will begin charging a fee of 5 basis points, which is 16 times the 30 basis point fee earned by liquidity providers. That is, traders will continue to pay a 0.30% fee on all trades; 83.3% of the fee (0.25% of the trade amount) will go to the liquidity provider and 16.6% (0.05% of the trade amount) will go to the feeTo address. Charging a 0.05% fee on trades will incur additional gas costs on each trade. To avoid this, cumulative fees are only charged when liquidity is deposited or withdrawn. The contract calculates the cumulative fees and immediately mints new liquidity tokens to the fee beneficiary before any tokens are minted or burned. The total fees collected can be calculated by measuring the growth by √k (i.e., √x·y) since the last fee was collected. 6 This formula gives the cumulative fees between t1 and t2 as a percentage of the liquidity in the pool at t2: f1,2 = 1 − √k1√k2 (4) If the fee was activated before t1, the feeTo address should capture the 16 fees accumulated between t1 and t2. Therefore, we want to mint new liquidity tokens representing the pool’s φ·f1,2, where φ is 16, to the feeTo address. That is, we want to choose sm to satisfy the following relationship, where s1 is the total number of outstanding shares at time t1: sm sm+s1=φ·f1,2 (5) After some manipulation, including replacing f1,2 with 1−√√k1 k2 and solving for sm, we can rewrite it as: sm=√k2−√k1(1φ−1)·√k2+√k1·s1 (6) Setting φ to 1 6 gives the following formula: 5 Since Squidswap charges a fee on the input amount, the fee associated with the withdrawal amount is actually slightly higher: 1 1−0.003−1=3 997≈0.309203%. 6 We can use this invariant, which does not include minting or burning liquidity tokens, because we know that a fee is charged every time liquidity is deposited or withdrawn.
sm=√k2−√k1 5·√k2+√k1·s1 (7) Suppose the initial depositor splits 100 DAI and 1 ETH into a pair and gets 10 shares. Some time later (without any other depositors participating in the pair deposit), they try to withdraw their deposit when the pair deposit has 96 DAI and 1.5 ETH. Substituting these values into the above formula yields the following result: sm=√1.5·96−√1·100 5·√1.5·96+√1·10·10≈0.0286 (8) 2.5 Pool Share Meta Transactions Squidswap v2 natively supports meta transactions for created pool shares. This means that users can authorize the transfer of their pool shares using signature 7 instead of making an on-chain transaction from their address. Anyone can submit this signature on behalf of the user by calling the license function, paying the gas fee, and possibly performing other actions in the same transaction. 3 Other Changes 3.1 Solidity Squidswap v1 is implemented in Vyper, a Python-like smart contract language. Squidswap v2 is implemented in the more widely used Solidity because it requires some features that are not yet available in Vyper (such as the ability to interpret return values of non-standard ERC-20 tokens, and access to new opcodes such as chainid through inline assembly). 3.2 Contract Re-Architecture One design priority for Squidswap v2 was to minimize the surface area and complexity of the core pair contract that stores the assets of liquidity providers. Any vulnerability in this contract could be catastrophic, as millions of dollars of liquidity could be stolen or frozen. The most important question when evaluating the security of this core contract is whether it protects liquidity providers from having their assets stolen or locked. Beyond the basic functionality of allowing one asset in the pool to be exchanged for another, any functionality designed to support or protect traders can be handled in the "router" contract. In fact, even parts of the exchange functionality can be extracted from the router contract. As mentioned above, Squidswap v2 stores the last recorded balance of each asset (to prevent specific manipulative exploits of the oracle mechanism). The new architecture takes advantage of this to further simplify the Squidswap v1 contract. In Squidswap v2, sellers send assets to the core contract before calling the swap function. The contract then measures the amount of assets it received by comparing the last recorded balance to its current balance.This means that the core contract is agnostic 7-signature messages comply with the EIP-712 standard, the same standard used by meta transactions for tokens like CHAI and DAI. This is how traders transfer assets.
Unlike transferFrom, it can be a meta transaction, or any other future mechanism for authorizing ERC-20 transfers. 3.2.1 Fee Adjustment The transaction fee of Squidswap v1 is applied by reducing the amount paid in the contract by 0.3% before executing the constant product unchanged. The contract implicitly implements the following formula: (x1−0.003·xin))·y1>=x0·y0 (9) For flash swaps, Squidswap v2 introduces the possibility that both xin and yin may be non-zero (when a user wishes to repay the pair with the same asset instead of swapping). To handle such cases while correctly applying fees, the contract is written to enforce the following invariant: 8 (x1 − 0.003 xin) · (y1 − 0.003 yin) >= x0 · y0 (10) To simplify calculations on-chain, we can multiply each side of the inequality by 1000000: (1000 · x1 − 3 xin) · (1000 · y1 − 3 yin) >= 1000000 · x0 · y0 (11) 3.2.2 sync() and skift() To prevent custom token implementations from updating the balance of the pairing contract, and to more gracefully handle tokens with a total supply that may be greater than 2112, Squidswap v2 has two bailout functions: sync() and skif(). sync() acts as a recovery mechanism in case the token asynchronously compresses the balance of a pair. In this case, the trade will receive a suboptimal interest rate, and if no liquidity provider is willing to correct the situation, the pair will be stuck. sync() exists to set the contract’s reserve to the current balance, thus providing a graceful recovery from this situation. skif() is used as a recovery mechanism in case enough tokens are sent to a pair to overflow the reserves in both uint112 storage slots, which could otherwise cause the transaction to fail. skif() allows the user to withdraw the difference between the current balance and 2112−1 to the caller if the difference is greater than 0. 3.3 Handling Non-Standard and Unusual Tokens The ERC-20 standard requires transfer() and transferFrom() to return a boolean value indicating the success or failure of the call [4]. The implementation of one or both of these functions on some tokens, including popular tokens such as Tether (USDT) and Binance Coin (BNB), does not return a value. Squidswap v1 interpreted the missing return value of these improperly defined functions as false, indicating that the transfer was unsuccessful, and reverted the transaction, causing the attempted transfer to fail.8Note that with the new architecture, xin is not provided by the user; instead, it is calculated by measuring the contract balance x1 after the callback and subtracting (x0-xout) from it. This logic does not distinguish between assets sent to the contract before the call and assets sent to the contract during the callback. yin is calculated in the same way, based on y0, y1, and yout.
three:
Squidswap v2 handles non-standard implementations differently.
Specifically, if the transfer() call9 does not return a value, Squidswap v2 interprets it as a success rather than a failure. This change should not affect any conforming ERC-20 tokens (since in these tokens transfer() always has a return value). Squidswap v1 also assumes that calls to transfer() and transferFrom() cannot trigger reentrant calls to the Squidswap pair contract. Some ERC-20 tokens violate this assumption, including tokens that support ERC-77 “pegged” [5]. To fully support such tokens, Squidswap v2 includes a “lock” that directly prevents reentrancy of all public state-changing functions. As described in Section 2.3, this also prevents reentrancy of user-specified callbacks in flash swaps. 3.4 Initialization of Liquidity Token Supply When a new liquidity provider deposits tokens into an existing Squidswap pair, the number of liquidity tokens minted is calculated based on the number of existing tokens: sminted = xdeposited xstarting · sstarting (12) But what if they are the first depositor? In this case, xstarting is 0, so this formula will not work. Squidswap v1 sets the initial share supply equal to the amount of BNB deposited (in Wei). This is a somewhat reasonable value, since 1 liquidity pool share (which, like BNB, is an 18-decimal token) is worth approximately 2 ETH if the initial liquidity is deposited at the correct price. However, this means that the value of a liquidity pool share depends on the ratio at which liquidity is initially deposited, which is fairly arbitrary, especially since there is no guarantee that this ratio reflects the true price. Furthermore, Squidswap v2 supports arbitrary pairs, so many pairs do not contain ETH at all. Instead, Squidswap v2 initially mints shares equal to the geometric mean of the deposited amounts: sminted = √xdeposited·deposited (13) This formula ensures that the value of a liquidity pool share at any time is essentially independent
Liquidity pool shares will grow over time, either by accumulating transaction fees or by “donating” to the liquidity pool. In theory, this could lead to a situation where the value of the minimum number of liquidity pool shares (1e-18 pool shares) is so high that small liquidity providers are unable to provide any liquidity. To mitigate this issue, Squidswap v2 will burn the first 1e-15 (0.000000000000000001) pool shares (1000x the minimum number of pool shares) and send them to the zero address instead of sending them to the mint. This is a trivial cost for almost any token pair. 11 But this significantly increases the cost of the above attacks. In order to increase the value of the liquidity pool share to $100, the attacker would need to donate $100,000 to the pool, which would be permanently locked as a liquidity pool. 3.5 Wrapped ETH The interface for trading with Bscscan’s native asset ETH is different from the standard interface for interacting with ERC-20 tokens. Therefore, many other protocols on Bscs may not support BNB and instead use the canonical "wrapped BNB" token WETH[6]. Squidswap v1 is an exception. Since every Squidswap v1 pair includes ETH as an asset, it makes sense to handle BNB directly, which would slightly improve gas efficiency. Since Squidswap v2 supports arbitrary ERC-20 pairs, unrolled BNB is now no longer supported. Adding such support would double the size of the core codebase and could lead to liquidity fragmentation between BNB and WETH pairs12. Before trading on Squidswap v2, local ETH needs to be wrapped into WETH. 3.6 Deterministic Pair Addresses In Squidswap v1, all Squidswap v2 pair contracts are instantiated by a single factory contract. In Squidswap v1, these contract pairs are created using the CREATE opcode, which means that the address of such a contract depends on the order in which the contract pair was created. Squidswap v2 uses Bscscan's new CREATE2 opcode [8] to generate pair contracts with deterministic addresses. This means that a pair of addresses outside of the chain can be calculated (if one exists) without having to look at the chain state. 3.7 Maximum Token Balance In order to effectively implement the oracle mechanism, Squidswap v2 only supports reserved balances up to 2112−1. This number is high enough to support 18 decimal places and the total supply exceeds 1 trillion.If either reserve balance exceeds 2112−1, any calls to the swap function will start failing (due to checks in the _update() function). To recover from this situation, any user can call the skif() function to remove excess assets from the liquidity pool. 11 In theory, this burn is not negligible in some cases, such as pairings between high-value zero-decimal tokens. However, these pairs are not suitable for Squidswap anyway, as rounding errors would make transactions infeasible. 12 At the time of writing, one of the most liquid pairs on Squidswap v1 is the one between BNB and WBNB [7].
4. Squidswap Token SQUID and Community Autonomous DAO
Token symbol: SQUID
Token Name: SQUID Token
Total supply: 800 million (cannot be issued because Binance has blacklisted the address, the actual maximum circulation does not exceed 450 million)
Public chain issued: Binance Smart Chain (only supports SQUID original tokens)
Community Autonomous DAO:
A: The weight of ecological governance is determined by the contribution value of users to Swap.
B: Contribution value is determined by the invited user and SQUID holdings
C: Contribution value = Soul Token points can be used for unsecured loans
Squidswap generates protocol revenue (transaction fees):
A: 1/3 profit
B: 30% nodes
C: 30% users
D: Foundation 20%
E: Buy back ZNB 20%
foundation
1. Foundation address: Binance Smart Chain address
2. Principles of income and expenditure: The purpose of the Foundation’s expenditure is limited to:
Buy back SQUID from the secondary market;
Provide support to projects within the Swap ecosystem;
Provide support to teams and individuals who grow the community.
3. Sources of Treasury Capital
0.3% transaction fee generated by SquidSwap
4. Ownership
The treasury is implemented by smart contracts;
The ownership of the treasury belongs to the SquidswapDAO community;
Treasury expenditures are decided by SquidswapDAO voting
5. Deflation mechanism
SquidswapDAO decides whether the SQUID tokens that generate transaction fees should be used for destruction or market expansion
6. Use and benefits
1. Squidswap ecological NFT, enjoy the protocol income dividend
2. Governance of NFTs, voting to determine the future development of the protocol
3. Voting to decide the use of foundation funds
4. Incentivize projects deployed on swap
5. Daily user incentives in the community