Skip to content

Commit

Permalink
Merge pull request #146 from consenlabs/limitorder-two-step-set-fee-f…
Browse files Browse the repository at this point in the history
…actors

Limitorder two-step set fee factors
  • Loading branch information
charlesjhongc authored Jan 17, 2023
2 parents 3c07f78 + a23af06 commit 99b7c6e
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
31 changes: 26 additions & 5 deletions contracts/LimitOrder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ contract LimitOrder is ILimitOrder, BaseLibEIP712, SignatureValidator, Reentranc
using SafeERC20 for IERC20;

string public constant version = "1.0.0";
uint256 public immutable factorActivateDelay;
IPermanentStorage public immutable permStorage;
address public immutable userProxy;
IWETH public immutable weth;
Expand All @@ -41,9 +42,13 @@ contract LimitOrder is ILimitOrder, BaseLibEIP712, SignatureValidator, Reentranc
address private nominatedOperator;

// Factors
uint256 public factorsTimeLock;
uint16 public makerFeeFactor = 0;
uint16 public pendingMakerFeeFactor;
uint16 public takerFeeFactor = 0;
uint16 public pendingTakerFeeFactor;
uint16 public profitFeeFactor = 0;
uint16 public pendingProfitFeeFactor;

constructor(
address _operator,
Expand All @@ -52,6 +57,7 @@ contract LimitOrder is ILimitOrder, BaseLibEIP712, SignatureValidator, Reentranc
ISpender _spender,
IPermanentStorage _permStorage,
IWETH _weth,
uint256 _factorActivateDelay,
address _uniswapV3RouterAddress,
address _sushiswapRouterAddress,
address _feeCollector
Expand All @@ -62,6 +68,7 @@ contract LimitOrder is ILimitOrder, BaseLibEIP712, SignatureValidator, Reentranc
spender = _spender;
permStorage = _permStorage;
weth = _weth;
factorActivateDelay = _factorActivateDelay;
uniswapV3RouterAddress = _uniswapV3RouterAddress;
sushiswapRouterAddress = _sushiswapRouterAddress;
feeCollector = _feeCollector;
Expand Down Expand Up @@ -139,7 +146,7 @@ contract LimitOrder is ILimitOrder, BaseLibEIP712, SignatureValidator, Reentranc
}
}

function setFactors(
function proposeFactors(
uint16 _makerFeeFactor,
uint16 _takerFeeFactor,
uint16 _profitFeeFactor
Expand All @@ -148,11 +155,25 @@ contract LimitOrder is ILimitOrder, BaseLibEIP712, SignatureValidator, Reentranc
require(_takerFeeFactor <= LibConstant.BPS_MAX, "LimitOrder: Invalid taker fee factor");
require(_profitFeeFactor <= LibConstant.BPS_MAX, "LimitOrder: Invalid profit fee factor");

makerFeeFactor = _makerFeeFactor;
takerFeeFactor = _takerFeeFactor;
profitFeeFactor = _profitFeeFactor;
pendingMakerFeeFactor = _makerFeeFactor;
pendingTakerFeeFactor = _takerFeeFactor;
pendingProfitFeeFactor = _profitFeeFactor;

emit FactorsUpdated(_makerFeeFactor, _takerFeeFactor, _profitFeeFactor);
factorsTimeLock = block.timestamp + factorActivateDelay;
}

function activateFactors() external {
require(factorsTimeLock != 0, "LimitOrder: no pending fee factors");
require(block.timestamp >= factorsTimeLock, "LimitOrder: fee factors timelocked");
factorsTimeLock = 0;
makerFeeFactor = pendingMakerFeeFactor;
takerFeeFactor = pendingTakerFeeFactor;
profitFeeFactor = pendingProfitFeeFactor;
pendingMakerFeeFactor = 0;
pendingTakerFeeFactor = 0;
pendingProfitFeeFactor = 0;

emit FactorsUpdated(makerFeeFactor, takerFeeFactor, profitFeeFactor);
}

/**
Expand Down
29 changes: 22 additions & 7 deletions contracts/test/forkMainnet/LimitOrder.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ contract LimitOrderTest is StrategySharedSetup {

LimitOrder limitOrder;
uint64 DEADLINE = uint64(block.timestamp + 2 days);
uint256 FACTORSDEALY = 12 hours;

// effectively a "beforeEach" block
function setUp() public {
Expand Down Expand Up @@ -149,6 +150,7 @@ contract LimitOrderTest is StrategySharedSetup {
ISpender(address(spender)),
IPermanentStorage(address(permanentStorage)),
IWETH(address(weth)),
FACTORSDEALY,
UNISWAP_V3_ADDRESS,
SUSHISWAP_ADDRESS,
feeCollector
Expand Down Expand Up @@ -177,6 +179,7 @@ contract LimitOrderTest is StrategySharedSetup {
assertEq(limitOrder.uniswapV3RouterAddress(), UNISWAP_V3_ADDRESS);
assertEq(limitOrder.sushiswapRouterAddress(), SUSHISWAP_ADDRESS);

assertEq(limitOrder.factorActivateDelay(), FACTORSDEALY);
assertEq(uint256(limitOrder.makerFeeFactor()), 0);
assertEq(uint256(limitOrder.takerFeeFactor()), 0);
assertEq(uint256(limitOrder.profitFeeFactor()), 0);
Expand Down Expand Up @@ -297,20 +300,28 @@ contract LimitOrderTest is StrategySharedSetup {
}

/*********************************
* Test: setFactors *
* Test: proposeFactors *
*********************************/

function testCannotSetFactorsIfLargerThanBpsMax() public {
vm.expectRevert("LimitOrder: Invalid maker fee factor");
limitOrder.setFactors(LibConstant.BPS_MAX + 1, 1, 1);
limitOrder.proposeFactors(LibConstant.BPS_MAX + 1, 1, 1);
vm.expectRevert("LimitOrder: Invalid taker fee factor");
limitOrder.setFactors(1, LibConstant.BPS_MAX + 1, 1);
limitOrder.proposeFactors(1, LibConstant.BPS_MAX + 1, 1);
vm.expectRevert("LimitOrder: Invalid profit fee factor");
limitOrder.setFactors(1, 1, LibConstant.BPS_MAX + 1);
limitOrder.proposeFactors(1, 1, LibConstant.BPS_MAX + 1);
}

function testSetFactors() public {
limitOrder.setFactors(1, 2, 3);
limitOrder.proposeFactors(1, 2, 3);
// fee factors should stay same before new ones activate
assertEq(uint256(limitOrder.makerFeeFactor()), 0);
assertEq(uint256(limitOrder.takerFeeFactor()), 0);
assertEq(uint256(limitOrder.profitFeeFactor()), 0);
vm.warp(block.timestamp + limitOrder.factorActivateDelay());

// fee factors should be updated now
limitOrder.activateFactors();
assertEq(uint256(limitOrder.makerFeeFactor()), 1);
assertEq(uint256(limitOrder.takerFeeFactor()), 2);
assertEq(uint256(limitOrder.profitFeeFactor()), 3);
Expand Down Expand Up @@ -610,7 +621,9 @@ contract LimitOrderTest is StrategySharedSetup {

// makerFeeFactor/takerFeeFactor : 10%
// profitFeeFactor : 20%
limitOrder.setFactors(1000, 1000, 2000);
limitOrder.proposeFactors(1000, 1000, 2000);
vm.warp(block.timestamp + limitOrder.factorActivateDelay());
limitOrder.activateFactors();

bytes memory payload = _genFillByTraderPayload(DEFAULT_ORDER, DEFAULT_ORDER_MAKER_SIG, DEFAULT_TRADER_PARAMS, DEFAULT_CRD_PARAMS);
vm.expectEmit(true, true, true, true);
Expand Down Expand Up @@ -1021,7 +1034,9 @@ contract LimitOrderTest is StrategySharedSetup {

// makerFeeFactor/takerFeeFactor : 10%
// profitFeeFactor : 20%
limitOrder.setFactors(1000, 1000, 2000);
limitOrder.proposeFactors(1000, 1000, 2000);
vm.warp(block.timestamp + limitOrder.factorActivateDelay());
limitOrder.activateFactors();

// get quote from AMM
uint256 ammTakerTokenOut = quoteUniswapV3ExactInput(DEFAULT_PROTOCOL_PARAMS.data, DEFAULT_ORDER.makerTokenAmount);
Expand Down

0 comments on commit 99b7c6e

Please sign in to comment.