|
| 1 | +// SPDX-License-Identifier: MIT |
| 2 | +pragma solidity ^0.8.26; |
| 3 | + |
| 4 | +import { BaseAlgorithm } from "./BaseAlgorithm.sol"; |
| 5 | +import { IAlgorithm } from "@async-swap/interfaces/IAlgorithm.sol"; |
| 6 | +import { AsyncOrder } from "@async-swap/types/AsyncOrder.sol"; |
| 7 | +import { TransientStorage } from "@async-swap/utils/TransientStorage.sol"; |
| 8 | +import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; |
| 9 | + |
| 10 | +/// @title Algorithm 2: Buy and Sell Ordering by Jiasun Li. |
| 11 | +/// @author Jiasun Li @ Async Labs |
| 12 | +/// @notice This contract implements the Algorithm 2 for ordering transactions. |
| 13 | +/// 1. lockBuy? := FALSE |
| 14 | +/// 2. lockSell? := FALSE |
| 15 | +/// 3. cumulatedVolume := 0 |
| 16 | +/// 4. beforeSwap: { |
| 17 | +/// get(isNextTxBuyX) ... {T or F} |
| 18 | +/// if(lockBuy? == TRUE) |
| 19 | +/// require(isNextTxBuyX? == TRUE) |
| 20 | +/// else |
| 21 | +/// if(lockSell? == TRUE) |
| 22 | +/// require(isNextTxBuyX? == FALSE) |
| 23 | +/// } |
| 24 | +/// 5. tx |
| 25 | +/// 6. afterSwap: { |
| 26 | +/// if (cumulatedVolume * nextTxBuyXVolume > 0){ |
| 27 | +/// switch(nextTxBuyXVolume>0){ |
| 28 | +/// case(TRUE): lockBuy? := TRUE |
| 29 | +/// case(FALSE): lockSell? := TRUE |
| 30 | +/// } |
| 31 | +/// } |
| 32 | +/// cumulatedVolume += nextTxBuyXVolume |
| 33 | +/// } |
| 34 | +contract Algorithm2 is BaseAlgorithm, TransientStorage { |
| 35 | + |
| 36 | + using SafeCast for *; |
| 37 | + |
| 38 | + /// keccak256("algorithm2.isPrevBuy"); |
| 39 | + bytes32 constant IS_PREV_BUY = 0x7e127a7bb2f4deeecd5997d5af18c995b303c3436532e9385868994ad2327421; |
| 40 | + /// keccak256("algorithm2.lockBuy"); |
| 41 | + bytes32 constant LOCK_BUY = 0x69f5f7eb44562f4b9ec1f74ec5e0ed336b22f83917380c9a63672de30dade5dd; |
| 42 | + /// keccak256("algorithm2.lockSell"); |
| 43 | + bytes32 constant LOCK_SELL = 0x052dd8f77e5de46dd4926f9e95c677f36f30fda8e014efe8c5d88724d6a4c9f8; |
| 44 | + /// keccak256("algorithm2.cummulativeAmount"); |
| 45 | + bytes32 constant CUMULATIVE_AMOUNT = 0xd54a46fd16a77402970e6a9bd6bbd09b1f768d3161ee91442eaa078698d0f85a; |
| 46 | + |
| 47 | + constructor(address _hookAddress) BaseAlgorithm(_hookAddress) { } |
| 48 | + |
| 49 | + /// @inheritdoc IAlgorithm |
| 50 | + function name() external pure override returns (string memory) { |
| 51 | + return "Algorithm2"; |
| 52 | + } |
| 53 | + |
| 54 | + /// @inheritdoc IAlgorithm |
| 55 | + function version() external pure override returns (string memory) { |
| 56 | + return "1.0.0"; |
| 57 | + } |
| 58 | + |
| 59 | + /// Determines if the next transaction is a buy or a sell. |
| 60 | + /// @param zeroForOne true if the next transaction is a buy (zeroForOne = true) or a sell (zeroForOne = false). |
| 61 | + function isBuy(bool zeroForOne) public pure returns (bool) { |
| 62 | + return zeroForOne ? true : false; |
| 63 | + } |
| 64 | + |
| 65 | + /// @inheritdoc IAlgorithm |
| 66 | + function orderingRule(bool zeroForOne, uint256 amount) external virtual override onlyHook { |
| 67 | + bool isNextBuy; |
| 68 | + bool isPrevBuy; |
| 69 | + bool lockBuy; |
| 70 | + bool lockSell; |
| 71 | + int256 cummulativeAmount; |
| 72 | + |
| 73 | + isPrevBuy = tload(IS_PREV_BUY) != 0x00; |
| 74 | + lockBuy = tload(LOCK_BUY) != 0x00; |
| 75 | + lockSell = tload(LOCK_SELL) != 0x00; |
| 76 | + cummulativeAmount = uint256(tload(CUMULATIVE_AMOUNT)).toInt256(); |
| 77 | + |
| 78 | + { |
| 79 | + // before excuting |
| 80 | + isNextBuy = isBuy(zeroForOne); |
| 81 | + if (lockBuy) { |
| 82 | + require(isNextBuy, "Buy order expected"); |
| 83 | + } else { |
| 84 | + if (lockSell) { |
| 85 | + require(!isNextBuy, "Sell order expected"); |
| 86 | + } |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + { |
| 91 | + // after executing |
| 92 | + if (cummulativeAmount > 0) { |
| 93 | + tstore(LOCK_BUY, 0x00); |
| 94 | + tstore(LOCK_SELL, 0x0000000000000000000000000000000000000000000000000000000000000001); |
| 95 | + } else { |
| 96 | + tstore(LOCK_BUY, 0x0000000000000000000000000000000000000000000000000000000000000001); |
| 97 | + tstore(LOCK_SELL, 0x00); |
| 98 | + } |
| 99 | + |
| 100 | + tstore( |
| 101 | + IS_PREV_BUY, |
| 102 | + isNextBuy |
| 103 | + ? bytes32(0x0000000000000000000000000000000000000000000000000000000000000001) |
| 104 | + : bytes32(0x0000000000000000000000000000000000000000000000000000000000000000) |
| 105 | + ); |
| 106 | + |
| 107 | + cummulativeAmount += zeroForOne ? int256(amount) : -int256(amount); |
| 108 | + } |
| 109 | + } |
| 110 | + |
| 111 | +} |
0 commit comments