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

feat: refactor #13

Merged
merged 21 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
262d728
BREAKING CHANGE: restructure factory to be behind TransparentUpgradea…
thaixuandang Aug 16, 2024
92d6672
chore: storage layout
thaixuandang Aug 16, 2024
165e5cb
fix: record only fees, not burned liquidity in the collectedFees method
thaixuandang Aug 19, 2024
fca3e10
chore: storage layout
thaixuandang Aug 19, 2024
a9196ef
chore: replace remapping by src directory
thaixuandang Aug 20, 2024
b841b15
chore: resolve comments
thaixuandang Aug 27, 2024
4dba1f6
fix: call msg.sender to get beacon when deploy pool proxy for compati…
thaixuandang Aug 27, 2024
d82d5d2
forge install: openzeppelin-contracts
thaixuandang Aug 28, 2024
ef1af86
fix: transfer protocol fees at the end of the swap to ensure pools ha…
thaixuandang Aug 29, 2024
333416f
chore: fix typo
thaixuandang Sep 6, 2024
f2a6905
feat: use storage variables instead of immutables in logic contracts
thaixuandang Sep 16, 2024
a786f73
feat(KatanaV3Pool): remove setFeeProtocol, collectProtocol functions
thaixuandang Sep 16, 2024
84b67dd
feat: split feeProtocol from single variable to 2 variables (numerato…
thaixuandang Sep 16, 2024
c8d1883
chore: storage layout
thaixuandang Sep 16, 2024
d86c4cf
chore(NonfungibleTokenPositionDescriptor): prioritized display of wel…
thaixuandang Sep 16, 2024
c60307b
chore: storage layout
thaixuandang Sep 16, 2024
54107fd
feat: update IKatanaGovernance
thaixuandang Sep 17, 2024
ecee4fb
chore: storage layout
thaixuandang Sep 17, 2024
3ffd563
feat(KatanaV3Factory): remove setOwner function
thaixuandang Sep 18, 2024
d772337
feat: update IKatanaGovernance
thaixuandang Sep 18, 2024
39a6e9d
chore: storage layout
thaixuandang Sep 18, 2024
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
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ libs = ["lib"]
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

solc = '0.7.6'
optimizer_runs = 800
optimizer_runs = 250
evm_version = 'istanbul'
TuDo1403 marked this conversation as resolved.
Show resolved Hide resolved
use_literal_content = true

Expand Down
47 changes: 23 additions & 24 deletions logs/contract-code-sizes.log
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,49 @@
| AddressStringUtil | 86 | 24,490 |
| AuthorizationLib | 86 | 24,490 |
| Base64 | 86 | 24,490 |
| BeaconProxy | 785 | 23,791 |
| BeaconProxy | 759 | 23,817 |
| BitMath | 86 | 24,490 |
| BytesLib | 86 | 24,490 |
| CallbackValidation | 86 | 24,490 |
| ChainId | 86 | 24,490 |
| ERC20 | 2,578 | 21,998 |
| Create2 | 86 | 24,490 |
| ERC20 | 2,546 | 22,030 |
| ERC20Mock | 3,518 | 21,058 |
| ERC721 | 6,650 | 17,926 |
| ERC721 | 6,557 | 18,019 |
| EnumerableMap | 86 | 24,490 |
| EnumerableSet | 86 | 24,490 |
| FixedPoint128 | 86 | 24,490 |
| FixedPoint96 | 86 | 24,490 |
| FullMath | 86 | 24,490 |
| HexStrings | 86 | 24,490 |
| KatanaGovernanceMock | 2,346 | 22,230 |
| KatanaInterfaceMulticall | 1,334 | 23,242 |
| KatanaGovernanceMock | 3,479 | 21,097 |
| KatanaInterfaceMulticall | 1,295 | 23,281 |
| KatanaV2Library | 86 | 24,490 |
| KatanaV2LibraryTestnet | 86 | 24,490 |
| KatanaV3Factory | 2,945 | 21,631 |
| KatanaV3FactoryProxy | 5,541 | 19,035 |
| KatanaV3Pool | 22,864 | 1,712 |
| KatanaV3PoolDeployer | 288 | 24,288 |
| KatanaV3PoolProxy | 1,248 | 23,328 |
| KatanaV3PoolProxyBytecode | 2,931 | 21,645 |
| KatanaV3Factory | 4,106 | 20,470 |
| KatanaV3Pool | 21,545 | 3,031 |
| KatanaV3PoolBeacon | 4,246 | 20,330 |
| KatanaV3PoolProxy | 1,209 | 23,367 |
| LiquidityAmounts | 86 | 24,490 |
| LiquidityMath | 86 | 24,490 |
| LowGasSafeMath | 86 | 24,490 |
| MixedRouteQuoterV1 | 7,328 | 17,248 |
| MixedRouteQuoterV1Testnet | 7,328 | 17,248 |
| NFTDescriptor | 23,833 | 743 |
| MixedRouteQuoterV1 | 7,220 | 17,356 |
| MixedRouteQuoterV1Testnet | 7,220 | 17,356 |
| NFTDescriptor | 23,372 | 1,204 |
| NFTSVG | 86 | 24,490 |
| NonfungiblePositionManager | 24,381 | 195 |
| NonfungibleTokenPositionDescriptor | 5,219 | 19,357 |
| NonfungiblePositionManager | 24,452 | 124 |
| NonfungibleTokenPositionDescriptor | 5,097 | 19,479 |
| Oracle | 86 | 24,490 |
| OracleLibrary | 86 | 24,490 |
| PairFlash | 5,510 | 19,066 |
| PairFlash | 5,428 | 19,148 |
| Path | 86 | 24,490 |
| PoolAddress | 86 | 24,490 |
| PoolTicksCounter | 86 | 24,490 |
| Position | 86 | 24,490 |
| PositionKey | 86 | 24,490 |
| PositionValue | 86 | 24,490 |
| Quoter | 3,944 | 20,632 |
| QuoterV2 | 7,103 | 17,473 |
| Quoter | 3,822 | 20,754 |
| QuoterV2 | 7,019 | 17,557 |
| SafeCast | 86 | 24,490 |
| SafeERC20Namer | 86 | 24,490 |
| SafeMath | 86 | 24,490 |
Expand All @@ -56,16 +55,16 @@
| SqrtPriceMathPartial | 86 | 24,490 |
| Strings | 86 | 24,490 |
| SwapMath | 86 | 24,490 |
| SwapRouter | 10,213 | 14,363 |
| SwapRouter | 9,945 | 14,631 |
| Tick | 86 | 24,490 |
| TickBitmap | 86 | 24,490 |
| TickLens | 1,349 | 23,227 |
| TickLens | 1,322 | 23,254 |
| TickMath | 86 | 24,490 |
| TokenRatioSortOrder | 86 | 24,490 |
| TransferHelper | 86 | 24,490 |
| TransparentUpgradeableProxy | 2,107 | 22,469 |
| TransparentUpgradeableProxy | 2,091 | 22,485 |
| UnsafeMath | 86 | 24,490 |
| UpgradeableBeacon | 1,208 | 23,368 |
| UpgradeableBeacon | 1,153 | 23,423 |
| UpgradeableProxy | 738 | 23,838 |
| V3Migrator | 6,084 | 18,492 |
| V3Migrator | 6,529 | 18,047 |

1 change: 0 additions & 1 deletion remappings.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
@uniswap/lib/contracts/=lib/solidity-lib/contracts/
base64-sol/=lib/base64/
@katana/v3-contracts/=src/
19 changes: 15 additions & 4 deletions script/DeployKatanaV3Core.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@
pragma solidity ^0.7.6;

import { Script, console } from "forge-std/Script.sol";
import { KatanaV3Factory } from "@katana/v3-contracts/core/KatanaV3Factory.sol";
import { KatanaV3FactoryProxy } from "@katana/v3-contracts/core/KatanaV3FactoryProxy.sol";
import { KatanaV3Factory } from "src/core/KatanaV3Factory.sol";
import { KatanaV3Pool } from "src/core/KatanaV3Pool.sol";
import { KatanaV3PoolBeacon } from "src/core/KatanaV3PoolBeacon.sol";
import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol";

abstract contract DeployKatanaV3Core is Script {
address public sender;
address public proxyAdmin;
address public governance;
address public treasury;

address poolImplementation;
address public beacon;
address public factory;

function setUp() public virtual {
Expand All @@ -22,12 +27,18 @@ abstract contract DeployKatanaV3Core is Script {
function run() public virtual {
vm.startBroadcast();

poolImplementation = address(new KatanaV3Pool());
beacon = address(new KatanaV3PoolBeacon(poolImplementation));

address factoryImplementation = address(new KatanaV3Factory());
factory = address(
new KatanaV3FactoryProxy(
factoryImplementation, proxyAdmin, abi.encodeWithSelector(KatanaV3Factory.initialize.selector, governance, treasury)
new TransparentUpgradeableProxy(
factoryImplementation,
proxyAdmin,
abi.encodeWithSelector(KatanaV3Factory.initialize.selector, beacon, governance, treasury)
)
);

console.log("KatanaV3Factory deployed:", factory);

vm.stopBroadcast();
Expand Down
17 changes: 9 additions & 8 deletions script/DeployKatanaV3Periphery.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ pragma solidity ^0.7.6;

import { Script, console } from "forge-std/Script.sol";
import { TransparentUpgradeableProxy } from "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol";
import { NonfungibleTokenPositionDescriptor } from
"@katana/v3-contracts/periphery/NonfungibleTokenPositionDescriptor.sol";
import { NonfungiblePositionManager } from "@katana/v3-contracts/periphery/NonfungiblePositionManager.sol";
import { V3Migrator } from "@katana/v3-contracts/periphery/V3Migrator.sol";
import { TickLens } from "@katana/v3-contracts/periphery/lens/TickLens.sol";
import { QuoterV2 } from "@katana/v3-contracts/periphery/lens/QuoterV2.sol";
import { KatanaInterfaceMulticall } from "@katana/v3-contracts/periphery/lens/KatanaInterfaceMulticall.sol";
import { NonfungibleTokenPositionDescriptor } from "src/periphery/NonfungibleTokenPositionDescriptor.sol";
import { NonfungiblePositionManager } from "src/periphery/NonfungiblePositionManager.sol";
import { V3Migrator } from "src/periphery/V3Migrator.sol";
import { TickLens } from "src/periphery/lens/TickLens.sol";
import { QuoterV2 } from "src/periphery/lens/QuoterV2.sol";
import { KatanaInterfaceMulticall } from "src/periphery/lens/KatanaInterfaceMulticall.sol";
import { DeployKatanaV3Core } from "./DeployKatanaV3Core.s.sol";

abstract contract DeployKatanaV3Periphery is DeployKatanaV3Core {
Expand Down Expand Up @@ -47,7 +46,9 @@ abstract contract DeployKatanaV3Periphery is DeployKatanaV3Core {
abi.encodeWithSelector(NonfungiblePositionManager.initialize.selector)
)
);
require(NonfungiblePositionManager(payable(nonfungiblePositionManager)).governance() == governance, "governance mismatch");
require(
NonfungiblePositionManager(payable(nonfungiblePositionManager)).governance() == governance, "governance mismatch"
);
console.log("NonfungiblePositionManager deployed:", nonfungiblePositionManager);

v3migrator = address(new V3Migrator(factory, wron, nonfungiblePositionManager));
Expand Down
8 changes: 5 additions & 3 deletions script/local/DeployKatanaV3Local.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ pragma solidity ^0.7.6;
import { Script } from "forge-std/Script.sol";
import { console } from "forge-std/console.sol";
import { DeployKatanaV3Periphery } from "../DeployKatanaV3Periphery.s.sol";
import { MixedRouteQuoterV1 } from "@katana/v3-contracts/periphery/lens/MixedRouteQuoterV1.sol";
import { KatanaGovernanceMock } from "@katana/v3-contracts/external/KatanaGovernanceMock.sol";
import { MixedRouteQuoterV1 } from "src/periphery/lens/MixedRouteQuoterV1.sol";
import { KatanaGovernanceMock } from "src/external/KatanaGovernanceMock.sol";
import { ERC20Mock } from "@openzeppelin/contracts/mocks/ERC20Mock.sol";

contract DeployKatanaV3Local is DeployKatanaV3Periphery {
address mixedRouteQuoterV1;

function setUp() public override {
proxyAdmin = makeAddr("ProxyAdmin");
governance = address(new KatanaGovernanceMock(address(0), address(0), true));
governance = address(new KatanaGovernanceMock(true));
treasury = makeAddr("RoninTreasury");
wron = address(new ERC20Mock("Wrapped Ronin", "WRON", address(this), 10 ** 9 * 10 ** 9));
factoryV2 = makeAddr("KatanaV2Factory");

sender = DEFAULT_SENDER;

super.setUp();
}

Expand Down
4 changes: 2 additions & 2 deletions script/ronin-mainnet/DeployKatanaV3Mainnet.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.7.6;
import { Script } from "forge-std/Script.sol";
import { console } from "forge-std/console.sol";
import { DeployKatanaV3Periphery } from "../DeployKatanaV3Periphery.s.sol";
import { MixedRouteQuoterV1 } from "@katana/v3-contracts/periphery/lens/MixedRouteQuoterV1.sol";
import { MixedRouteQuoterV1 } from "src/periphery/lens/MixedRouteQuoterV1.sol";

contract DeployKatanaV3Mainnet is DeployKatanaV3Periphery {
address mixedRouteQuoterV1;
Expand All @@ -16,7 +16,7 @@ contract DeployKatanaV3Mainnet is DeployKatanaV3Periphery {
wron = 0xe514d9DEB7966c8BE0ca922de8a064264eA6bcd4; // WRON
factoryV2 = 0xB255D6A720BB7c39fee173cE22113397119cB930; // Katana V2 Factory

vm.rememberKey(vm.envUint("MAINNET_PK"));
sender = vm.rememberKey(vm.envUint("MAINNET_PK"));

super.setUp();
}
Expand Down
4 changes: 2 additions & 2 deletions script/ronin-testnet/DeployKatanaV3Testnet.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.7.6;
import { Script } from "forge-std/Script.sol";
import { console } from "forge-std/console.sol";
import { DeployKatanaV3Periphery } from "../DeployKatanaV3Periphery.s.sol";
import { MixedRouteQuoterV1Testnet } from "@katana/v3-contracts/periphery/lens/MixedRouteQuoterV1Testnet.sol";
import { MixedRouteQuoterV1Testnet } from "src/periphery/lens/MixedRouteQuoterV1Testnet.sol";

contract DeployKatanaV3Testnet is DeployKatanaV3Periphery {
address mixedRouteQuoterV1Testnet;
Expand All @@ -16,7 +16,7 @@ contract DeployKatanaV3Testnet is DeployKatanaV3Periphery {
wron = 0xA959726154953bAe111746E265E6d754F48570E6;
factoryV2 = 0x86587380C4c815Ba0066c90aDB2B45CC9C15E72c;

vm.rememberKey(vm.envUint("TESTNET_PK"));
sender = vm.rememberKey(vm.envUint("TESTNET_PK"));

super.setUp();
}
Expand Down
79 changes: 45 additions & 34 deletions src/core/KatanaV3Factory.sol
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.7.6;

import "@openzeppelin/contracts/proxy/UpgradeableBeacon.sol";

import "./interfaces/IKatanaV3Factory.sol";

import "./KatanaV3PoolDeployer.sol";

import "./KatanaV3Pool.sol";

import "../external/libraries/AuthorizationLib.sol";
import "../external/interfaces/IKatanaGovernance.sol";

/// @title Canonical Katana V3 factory
/// @notice Deploys Katana V3 pools and manages ownership and control over pool protocol fees
contract KatanaV3Factory is IKatanaV3Factory, KatanaV3PoolDeployer {
struct Fraction {
uint8 numerator;
uint8 denominator;
}

/// @inheritdoc IKatanaV3Factory
address public override owner;
/// @inheritdoc IKatanaV3Factory
Expand All @@ -24,20 +25,30 @@ contract KatanaV3Factory is IKatanaV3Factory, KatanaV3PoolDeployer {
/// @inheritdoc IKatanaV3Factory
mapping(uint24 => int24) public override feeAmountTickSpacing;
/// @inheritdoc IKatanaV3Factory
mapping(uint24 => uint16) public override feeAmountProtocol;
mapping(uint24 => Fraction) public override feeAmountProtocol;
/// @inheritdoc IKatanaV3Factory
mapping(address => mapping(address => mapping(uint24 => address))) public override getPool;

/// @dev Whether the factory has been initialized
bool private _initialized;

constructor() {
// disable initialization
_initialized = true;
beacon = address(1);
}

function initialize(address owner_, address treasury_) external {
require(!_initialized);
modifier onlyOwner() {
_checkOwner();
_;
}

function _checkOwner() internal view virtual {
require(owner == msg.sender, "KatanaV3Factory: FORBIDDEN");
}

function initialize(address beacon_, address owner_, address treasury_) external {
require(beacon == address(0), "KatanaV3Factory: ALREADY_INITIALIZED");

// this beacon is treated as immutable
// so there is no need to emit an event
beacon = beacon_;
TuDo1403 marked this conversation as resolved.
Show resolved Hide resolved

owner = owner_;
emit OwnerChanged(address(0), owner_);
Expand All @@ -47,22 +58,20 @@ contract KatanaV3Factory is IKatanaV3Factory, KatanaV3PoolDeployer {

// swap fee 0.01% = 0.005% for LP + 0.005% for protocol
// tick spacing of 1, equivalent to 0.01% between initializable ticks
_enableFeeAmount(100, 1, 5 | (10 << 8));
_enableFeeAmount(100, 1, 5, 10);

// swap fee 0.3% = 0.25% for LP + 0.05% for protocol
// tick spacing of 60, approximately 0.60% between initializable ticks
_enableFeeAmount(3000, 60, 5 | (30 << 8));
_enableFeeAmount(3000, 60, 5, 30);

// swap fee 1% = 0.85% for LP + 0.15% for protocol
// tick spacing of 200, approximately 2.02% between initializable ticks
_enableFeeAmount(10000, 200, 15 | (100 << 8));

_initialized = true;
_enableFeeAmount(10000, 200, 15, 100);
}

/// @inheritdoc IKatanaV3Factory
function createPool(address tokenA, address tokenB, uint24 fee) external override returns (address pool) {
AuthorizationLib.checkPositionManager(owner);
require(msg.sender == IKatanaGovernance(owner).getPositionManager(), "KatanaV3Factory: INVALID_POSITION_MANAGER");
thaixuandang marked this conversation as resolved.
Show resolved Hide resolved

require(tokenA != tokenB);
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
Expand All @@ -78,40 +87,42 @@ contract KatanaV3Factory is IKatanaV3Factory, KatanaV3PoolDeployer {
}

/// @inheritdoc IKatanaV3Factory
function setOwner(address _owner) external override {
require(msg.sender == owner);
function setOwner(address _owner) external override onlyOwner {
emit OwnerChanged(owner, _owner);
owner = _owner;
}
TuDo1403 marked this conversation as resolved.
Show resolved Hide resolved

function setTreasury(address _treasury) external override {
require(msg.sender == owner);
function setTreasury(address _treasury) external override onlyOwner {
require(_treasury != address(0), "KatanaV3Factory: INVALID_TREASURY");
emit TreasuryChanged(treasury, _treasury);
treasury = _treasury;
thaixuandang marked this conversation as resolved.
Show resolved Hide resolved
}

function toggleFlashLoanPermission() external override {
require(msg.sender == owner);
function toggleFlashLoanPermission() external override onlyOwner {
flashLoanEnabled = !flashLoanEnabled;
emit FlashLoanPermissionUpdated(flashLoanEnabled);
}

/// @inheritdoc IKatanaV3Factory
function enableFeeAmount(uint24 fee, int24 tickSpacing, uint16 feeProtocol) public override {
require(msg.sender == owner);
require(fee < 1000000);
function enableFeeAmount(uint24 fee, int24 tickSpacing, uint8 feeProtocolNum, uint8 feeProtocolDen)
public
override
onlyOwner
{
require(fee < 1000000, "KatanaV3Factory: FEE_TOO_HIGH");
thaixuandang marked this conversation as resolved.
Show resolved Hide resolved
// tick spacing is capped at 16384 to prevent the situation where tickSpacing is so large that
// TickBitmap#nextInitializedTickWithinOneWord overflows int24 container from a valid tick
// 16384 ticks represents a >5x price change with ticks of 1 bips
require(tickSpacing > 0 && tickSpacing < 16384);
require((feeProtocol & 255) < (feeProtocol >> 8));
require(feeAmountTickSpacing[fee] == 0);
require(tickSpacing > 0 && tickSpacing < 16384, "KatanaV3Factory: INVALID_TICK_SPACING");
require(feeProtocolNum < feeProtocolDen, "KatanaV3Factory: INVALID_FEE_PROTOCOL");
thaixuandang marked this conversation as resolved.
Show resolved Hide resolved
require(feeAmountTickSpacing[fee] == 0, "KatanaV3Factory: FEE_AMOUNT_ALREADY_ENABLED");

_enableFeeAmount(fee, tickSpacing, feeProtocol);
_enableFeeAmount(fee, tickSpacing, feeProtocolNum, feeProtocolDen);
}

function _enableFeeAmount(uint24 fee, int24 tickSpacing, uint16 feeProtocol) private {
function _enableFeeAmount(uint24 fee, int24 tickSpacing, uint8 feeProtocolNum, uint8 feeProtocolDen) private {
feeAmountTickSpacing[fee] = tickSpacing;
feeAmountProtocol[fee] = feeProtocol;
emit FeeAmountEnabled(fee, tickSpacing, feeProtocol);
feeAmountProtocol[fee] = Fraction(feeProtocolNum, feeProtocolDen);
emit FeeAmountEnabled(fee, tickSpacing, feeProtocolNum, feeProtocolDen);
}
}
Loading