Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get min keeper fee command #174

Merged
merged 15 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 100 additions & 95 deletions .gas-snapshot

Large diffs are not rendered by default.

Binary file not shown.
2 changes: 1 addition & 1 deletion deploy-addresses/optimism-goerli.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"Account": "0x0fCeF9608B9F7a8C57D53B98E78fA64b4D786a9F",
"Account": "0x5f78a5EdF0B356F50886a6829Fc02B16532e8735",
"Events": "0xe32F27B27F4ea5f10f269b52223910bA83e2933C",
"Factory": "0x30582eeE34719fe22b1B6c3b607636A3ab94522E",
"Settings": "0x8B9CbD3da94c637c0652c680Abd3CF7f787aBAF4"
Expand Down
2 changes: 1 addition & 1 deletion deploy-addresses/optimism.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"Account": "0x83E13069aA457778ca349E0128927B417A2c2B3f",
"Account": "0x6B86c1A6878940666489780871E1C98B366d0aFF",
"Events": "0xB753d2EE5dcA1fF39A83CA3Ec500656c31Be940b",
"Factory": "0x8234F990b149Ae59416dc260305E565e5DAfEb54",
"Settings": "0x865dA103d126b3Be3599D84caB57109A861F5631"
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@kwenta/cross-margin-manager",
"version": "2.1.0",
"version": "2.1.1",
"scripts": {
"compile": "forge build",
"test": "forge test --fork-url $(grep ARCHIVE_NODE_URL_L2 .env | cut -d '=' -f2) --etherscan-api-key $(grep ETHERSCAN_API_KEY .env | cut -d '=' -f2) --gas-report -vvv",
Expand Down
129 changes: 129 additions & 0 deletions script/upgrades/v2.1.1/Upgrade.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.18;

import {Script} from "lib/forge-std/src/Script.sol";

import {IAddressResolver} from "script/utils/interfaces/IAddressResolver.sol";

import {Account} from "src/Account.sol";
import {Events} from "src/Events.sol";
import {Settings} from "src/Settings.sol";
import {IAccount} from "src/interfaces/IAccount.sol";

import {
OPTIMISM_PDAO,
OPTIMISM_GELATO,
OPTIMISM_OPS,
FUTURES_MARKET_MANAGER,
OPTIMISM_FACTORY,
OPTIMISM_EVENTS,
OPTIMISM_SETTINGS,
OPTIMISM_SYNTHETIX_ADDRESS_RESOLVER,
OPTIMISM_UNISWAP_PERMIT2,
OPTIMISM_UNISWAP_UNIVERSAL_ROUTER,
PERPS_V2_EXCHANGE_RATE,
PROXY_SUSD,
SYSTEM_STATUS
} from "script/utils/parameters/OptimismParameters.sol";
import {
OPTIMISM_GOERLI_DEPLOYER,
OPTIMISM_GOERLI_EVENTS,
OPTIMISM_GOERLI_SETTINGS,
OPTIMISM_GOERLI_FACTORY,
OPTIMISM_GOERLI_GELATO,
OPTIMISM_GOERLI_OPS,
OPTIMISM_GOERLI_SYNTHETIX_ADDRESS_RESOLVER,
OPTIMISM_GOERLI_UNISWAP_PERMIT2,
OPTIMISM_GOERLI_UNISWAP_UNIVERSAL_ROUTER
} from "script/utils/parameters/OptimismGoerliParameters.sol";

/// @title Script to upgrade the Account implementation v2.1.0 -> v2.1.1
/// @author JaredBorders ([email protected])

/// @dev steps to deploy and verify on Optimism:
/// (1) load the variables in the .env file via `source .env`
/// (2) run `forge script script/upgrades/v2.1.1/Upgrade.s.sol:UpgradeAccountOptimism --rpc-url $ARCHIVE_NODE_URL_L2 --broadcast --verify -vvvv`
/// (3) Smart Margin Account Factory owner (i.e. Kwenta pDAO) will need to call `upgradeAccountImplementation` on the Factory with the address of the new Account implementation
contract UpgradeAccountOptimism is Script {
function run() public {
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);

upgrade();

vm.stopBroadcast();
}

function upgrade() public returns (address implementation) {
IAddressResolver addressResolver =
IAddressResolver(OPTIMISM_SYNTHETIX_ADDRESS_RESOLVER);

address marginAsset = addressResolver.getAddress({name: PROXY_SUSD});
address perpsV2ExchangeRate =
addressResolver.getAddress({name: PERPS_V2_EXCHANGE_RATE});
address futuresMarketManager =
addressResolver.getAddress({name: FUTURES_MARKET_MANAGER});
address systemStatus = addressResolver.getAddress({name: SYSTEM_STATUS});

IAccount.AccountConstructorParams memory params = IAccount
.AccountConstructorParams({
factory: OPTIMISM_FACTORY,
events: OPTIMISM_EVENTS,
marginAsset: marginAsset,
perpsV2ExchangeRate: perpsV2ExchangeRate,
futuresMarketManager: futuresMarketManager,
systemStatus: systemStatus,
gelato: OPTIMISM_GELATO,
ops: OPTIMISM_OPS,
settings: OPTIMISM_SETTINGS,
universalRouter: OPTIMISM_UNISWAP_UNIVERSAL_ROUTER,
permit2: OPTIMISM_UNISWAP_PERMIT2
});

implementation = address(new Account(params));
}
}

/// @dev steps to deploy and verify on Optimism Goerli:
/// (1) load the variables in the .env file via `source .env`
/// (2) run `forge script script/upgrades/v2.1.1/Upgrade.s.sol:UpgradeAccountOptimismGoerli --rpc-url $ARCHIVE_NODE_URL_GOERLI_L2 --broadcast --verify -vvvv`
/// (3) Smart Margin Account Factory owner (i.e. Kwenta pDAO) will need to call `upgradeAccountImplementation` on the Factory with the address of the new Account implementation
contract UpgradeAccountOptimismGoerli is Script {
function run() public {
uint256 deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);

upgrade();

vm.stopBroadcast();
}

function upgrade() public returns (address implementation) {
IAddressResolver addressResolver =
IAddressResolver(OPTIMISM_GOERLI_SYNTHETIX_ADDRESS_RESOLVER);

address marginAsset = addressResolver.getAddress({name: PROXY_SUSD});
address perpsV2ExchangeRate =
addressResolver.getAddress({name: PERPS_V2_EXCHANGE_RATE});
address futuresMarketManager =
addressResolver.getAddress({name: FUTURES_MARKET_MANAGER});
address systemStatus = addressResolver.getAddress({name: SYSTEM_STATUS});

IAccount.AccountConstructorParams memory params = IAccount
.AccountConstructorParams({
factory: OPTIMISM_GOERLI_FACTORY,
events: OPTIMISM_GOERLI_EVENTS,
marginAsset: marginAsset,
perpsV2ExchangeRate: perpsV2ExchangeRate,
futuresMarketManager: futuresMarketManager,
systemStatus: systemStatus,
gelato: OPTIMISM_GOERLI_GELATO,
ops: OPTIMISM_GOERLI_OPS,
settings: OPTIMISM_GOERLI_SETTINGS,
universalRouter: OPTIMISM_GOERLI_UNISWAP_UNIVERSAL_ROUTER,
permit2: OPTIMISM_GOERLI_UNISWAP_PERMIT2
});

implementation = address(new Account(params));
}
}
10 changes: 5 additions & 5 deletions script/utils/parameters/OptimismGoerliParameters.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ address constant OPTIMISM_GOERLI_GELATO =
address constant OPTIMISM_GOERLI_OPS =
0x255F82563b5973264e89526345EcEa766DB3baB2;

// v2.1.0
// v2.1.1
address constant OPTIMISM_GOERLI_IMPLEMENTATION =
0x0fCeF9608B9F7a8C57D53B98E78fA64b4D786a9F;
0x5f78a5EdF0B356F50886a6829Fc02B16532e8735;

// released with v2.1.0 implementation
// released with v2.1.0 implementation (used by v2.1.*)
address constant OPTIMISM_GOERLI_EVENTS =
0xe32F27B27F4ea5f10f269b52223910bA83e2933C;

// updated with v2.1.0 implementation
// updated with v2.1.1 implementation
address constant OPTIMISM_GOERLI_FACTORY =
0x30582eeE34719fe22b1B6c3b607636A3ab94522E;

// released with v2.1.0 implementation
// released with v2.1.0 implementation (used by v2.1.*)
address constant OPTIMISM_GOERLI_SETTINGS =
0x8B9CbD3da94c637c0652c680Abd3CF7f787aBAF4;

Expand Down
12 changes: 6 additions & 6 deletions script/utils/parameters/OptimismParameters.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.18;
/// @dev for Synthetix addresses see:
/// https://github.com/Synthetixio/synthetix-docs/blob/master/content/addresses.md#mainnet-optimism-l2

// v2.1.0 deployer
// v2.1.1 deployer
address constant OPTIMISM_DEPLOYER = 0xb7CefE980D41F2f83d4272526b0A0F04617da96b;

address constant OPTIMISM_PDAO = 0xe826d43961a87fBE71C91d9B73F7ef9b16721C07;
Expand All @@ -16,17 +16,17 @@ address constant OPTIMISM_GELATO = 0x01051113D81D7d6DA508462F2ad6d7fD96cF42Ef;

address constant OPTIMISM_OPS = 0x340759c8346A1E6Ed92035FB8B6ec57cE1D82c2c;

// v2.1.0
// v2.1.1
address constant OPTIMISM_IMPLEMENTATION =
0x83E13069aA457778ca349E0128927B417A2c2B3f;
0x6B86c1A6878940666489780871E1C98B366d0aFF;

// released with v2.1.0 implementation
// released with v2.1.0 implementation (used by v2.1.*)
address constant OPTIMISM_EVENTS = 0xB753d2EE5dcA1fF39A83CA3Ec500656c31Be940b;

// updated with v2.1.0 implementation
// updated with v2.1.1 implementation
address constant OPTIMISM_FACTORY = 0x8234F990b149Ae59416dc260305E565e5DAfEb54;

// released with v2.1.0 implementation
// released with v2.1.0 implementation (used by v2.1.*)
address constant OPTIMISM_SETTINGS = 0x865dA103d126b3Be3599D84caB57109A861F5631;

// key(s) used by Synthetix address resolver
Expand Down
19 changes: 16 additions & 3 deletions src/Account.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {ISystemStatus} from "src/interfaces/synthetix/ISystemStatus.sol";
import {IOps} from "src/interfaces/gelato/IOps.sol";
import {IUniversalRouter} from "src/interfaces/uniswap/IUniversalRouter.sol";
import {IEvents} from "src/interfaces/IEvents.sol";
import {IPerpsV2DynamicFeesModule} from
"src/interfaces/synthetix/IPerpsV2DynamicFeesModule.sol";
import {IPerpsV2ExchangeRate} from
"src/interfaces/synthetix/IPerpsV2ExchangeRate.sol";
import {OpsReady} from "src/utils/gelato/OpsReady.sol";
Expand All @@ -35,7 +37,7 @@ contract Account is IAccount, Auth, OpsReady {
//////////////////////////////////////////////////////////////*/

/// @inheritdoc IAccount
bytes32 public constant VERSION = "2.1.0";
bytes32 public constant VERSION = "2.1.1";

/// @notice tracking code used when modifying positions
bytes32 internal constant TRACKING_CODE = "KWENTA";
Expand All @@ -48,6 +50,11 @@ contract Account is IAccount, Auth, OpsReady {
/// @dev specifically for swapping exact tokens in for a non-exact amount of tokens out
uint256 internal constant V3_SWAP_EXACT_IN = 0x00;

/// @notice Synthetix Dynamic Fees Module
/// @dev address will never change and only exists on Optimism Mainnet
IPerpsV2DynamicFeesModule internal constant PERPS_V2_DYNAMIC_FEES_MODULE =
IPerpsV2DynamicFeesModule(0xF4bc5588aAB8CBB412baDd3674094ECF808286f6);

/*//////////////////////////////////////////////////////////////
IMMUTABLES
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -480,8 +487,14 @@ contract Account is IAccount, Auth, OpsReady {
}
_cancelConditionalOrder({_conditionalOrderId: orderId});
}
} else if (commandIndex > 15) {
// commandIndex 14 & 15 valid and already checked
} else if (commandIndex == 16) {
/// @dev command indices 14 and 15 have already been checked
// Command.PERPS_V2_SET_MIN_KEEPER_FEE
if (!PERPS_V2_DYNAMIC_FEES_MODULE.setMinKeeperFee()) {
revert SetMinKeeperFeeFailed();
}
} else {
// command indices beyond 16 are invalid
revert InvalidCommandType(commandIndex);
}
}
Expand Down
8 changes: 6 additions & 2 deletions src/interfaces/IAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity 0.8.18;
import {IPerpsV2MarketConsolidated} from
"src/interfaces/synthetix/IPerpsV2MarketConsolidated.sol";

/// @title Kwenta Smart Margin Account v2.1.0 Implementation Interface
/// @title Kwenta Smart Margin Account v2.1.1 Implementation Interface
/// @author JaredBorders ([email protected]), JChiaramonte7 ([email protected])
interface IAccount {
/*///////////////////////////////////////////////////////////////
Expand All @@ -29,7 +29,8 @@ interface IAccount {
GELATO_PLACE_CONDITIONAL_ORDER,
GELATO_CANCEL_CONDITIONAL_ORDER,
UNISWAP_V3_SWAP,
PERMIT2_PERMIT // 15
PERMIT2_PERMIT, // 15
PERPS_V2_SET_MIN_KEEPER_FEE
}

/// @notice denotes conditional order types for code clarity
Expand Down Expand Up @@ -154,6 +155,9 @@ interface IAccount {
/// @param executorFee: fee required to execute conditional order
error CannotPayExecutorFee(uint256 executorFee, address executor);

/// @notice thrown when call to set/updates the min keeper fee fails
error SetMinKeeperFeeFailed();

/*//////////////////////////////////////////////////////////////
VIEWS
//////////////////////////////////////////////////////////////*/
Expand Down
20 changes: 20 additions & 0 deletions src/interfaces/synthetix/IPerpsV2DynamicFeesModule.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.18;

interface IPerpsV2DynamicFeesModule {
/// @dev Updates the minKeeperFee in PerpsV2MarketSettings
function setMinKeeperFee() external returns (bool success);

function getParameters()
external
view
returns (
uint256 profitMarginUSD,
uint256 profitMarginPercent,
uint256 minKeeperFeeUpperBound,
uint256 minKeeperFeeLowerBound,
uint256 gasUnitsL1,
uint256 gasUnitsL2,
uint256 lastUpdatedAtTime
);
}
40 changes: 39 additions & 1 deletion test/integration/margin.behavior.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import {Factory} from "src/Factory.sol";
import {IAccount} from "src/interfaces/IAccount.sol";
import {IFuturesMarketManager} from
"src/interfaces/synthetix/IFuturesMarketManager.sol";
import {IPermit2} from "src/interfaces/uniswap/IPermit2.sol";
import {IPerpsV2MarketConsolidated} from "src/interfaces/IAccount.sol";
import {IPerpsV2DynamicFeesModule} from
"src/interfaces/synthetix/IPerpsV2DynamicFeesModule.sol";
import {IERC20} from "src/interfaces/token/IERC20.sol";

import {AccountExposed} from "test/utils/AccountExposed.sol";
Expand All @@ -28,6 +29,7 @@ import {
FUTURES_MARKET_MANAGER,
GELATO,
OPS,
PERPS_V2_DYNAMIC_FEES_MODULE,
PERPS_V2_EXCHANGE_RATE,
PROXY_SUSD,
sETHPERP,
Expand Down Expand Up @@ -725,6 +727,42 @@ contract MarginBehaviorTest is Test, ConsolidatedEvents {
assert(order.sizeDelta == -sizeDelta);
}

function test_Commands_SetMinKeeperFee() public {
IAccount.Command[] memory commands = new IAccount.Command[](1);
bytes[] memory inputs = new bytes[](1);

commands[0] = IAccount.Command.PERPS_V2_SET_MIN_KEEPER_FEE;
inputs[0] = abi.encode(0);

account.execute(commands, inputs);

(,,,,,, uint256 lastUpdatedAtTime) = IPerpsV2DynamicFeesModule(
PERPS_V2_DYNAMIC_FEES_MODULE
).getParameters();

assertEq(lastUpdatedAtTime, block.timestamp);
}

function test_Commands_SetMinKeeperFee_Fails() public {
vm.mockCall(
PERPS_V2_DYNAMIC_FEES_MODULE,
abi.encodeWithSignature("setMinKeeperFee()"),
abi.encode(false)
);

IAccount.Command[] memory commands = new IAccount.Command[](1);
bytes[] memory inputs = new bytes[](1);

commands[0] = IAccount.Command.PERPS_V2_SET_MIN_KEEPER_FEE;
inputs[0] = abi.encode(0);

vm.expectRevert(
abi.encodeWithSelector(IAccount.SetMinKeeperFeeFailed.selector)
);

account.execute(commands, inputs);
}

/*//////////////////////////////////////////////////////////////
SCENARIOS
//////////////////////////////////////////////////////////////*/
Expand Down
Loading