Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: innovation zone
Browse files Browse the repository at this point in the history
thaixuandang committed Jul 31, 2024
1 parent 289eaae commit f4ea030
Showing 13 changed files with 452 additions and 249 deletions.
2 changes: 1 addition & 1 deletion lib/katana-v3-contracts
Submodule katana-v3-contracts updated 39 files
+0 −3 .gitmodules
+7 −0 Makefile
+1 −3 foundry.toml
+0 −1 lib/v2-core
+0 −1 remappings.txt
+38 −0 script/DeployKatanaV3Core.s.sol
+73 −0 script/DeployKatanaV3Periphery.s.sol
+30 −0 script/local/DeployKatanaV3Local.s.sol
+30 −0 script/ronin-mainnet/DeployKatanaV3Mainnet.s.sol
+30 −0 script/ronin-testnet/DeployKatanaV3Testnet.s.sol
+19 −14 src/core/KatanaV3Factory.sol
+31 −0 src/core/KatanaV3FactoryProxy.sol
+8 −0 src/core/KatanaV3Pool.sol
+7 −3 src/core/KatanaV3PoolDeployer.sol
+6 −3 src/core/KatanaV3PoolProxy.sol
+16 −0 src/core/KatanaV3PoolProxyBytecode.sol
+0 −4 src/core/interfaces/IKatanaV3Factory.sol
+14 −0 src/core/interfaces/IKatanaV3FactoryImmutables.sol
+2 −0 src/core/interfaces/IKatanaV3Pool.sol
+14 −0 src/core/interfaces/pool/IKatanaV3PoolImmutablesInitializable.sol
+87 −0 src/external/KatanaGovernanceMock.sol
+134 −0 src/external/interfaces/IKatanaGovernance.sol
+25 −0 src/external/libraries/AuthorizationLib.sol
+60 −1 src/periphery/NonfungiblePositionManager.sol
+3 −3 src/periphery/V3Migrator.sol
+18 −0 src/periphery/base/ImmutableState.sol
+4 −0 src/periphery/base/PoolInitializer.sol
+12 −0 src/periphery/interfaces/IImmutableState.sol
+53 −0 src/periphery/interfaces/IKatanaV2Pair.sol
+67 −0 src/periphery/interfaces/IMixedRouteQuoterV1.sol
+6 −0 src/periphery/interfaces/INonfungiblePositionManager.sol
+194 −0 src/periphery/lens/MixedRouteQuoterV1.sol
+194 −0 src/periphery/lens/MixedRouteQuoterV1Testnet.sol
+86 −0 src/periphery/libraries/KatanaV2Library.sol
+86 −0 src/periphery/libraries/KatanaV2LibraryTestnet.sol
+3 −2 src/periphery/libraries/PoolAddress.sol
+22 −4 test/core/KatanaV3Factory.t.sol
+72 −20 test/core/KatanaV3Pool.t.sol
+17 −0 test/core/PoolProxyInitCodeHash.t.sol
5 changes: 1 addition & 4 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
@fdk/=lib/foundry-deployment-kit/script/
@contract-libs/=lib/foundry-deployment-kit/lib/contract-libs/src/
forge-std/=lib/foundry-deployment-kit/lib/forge-std/src/
@solady/=lib/foundry-deployment-kit/lib/solady/src/
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
solmate/=lib/solmate/
permit2/=lib/permit2/
@katana/v3-contracts/=lib/katana-v3-contracts/src/
45 changes: 0 additions & 45 deletions script/GeneralConfig.sol

This file was deleted.

31 changes: 0 additions & 31 deletions script/Migration.s.sol

This file was deleted.

26 changes: 0 additions & 26 deletions script/SDK.sol

This file was deleted.

12 changes: 0 additions & 12 deletions script/interfaces/ISharedArgument.sol

This file was deleted.

19 changes: 0 additions & 19 deletions script/utils/Contract.sol

This file was deleted.

56 changes: 0 additions & 56 deletions script/utils/Network.sol

This file was deleted.

53 changes: 0 additions & 53 deletions src/aggregate-router/interfaces/external/IKatanaV2Pair.sol

This file was deleted.

2 changes: 1 addition & 1 deletion src/aggregate-router/modules/katana/v2/KatanaV2Library.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;

import { IKatanaV2Pair } from "../../../interfaces/external/IKatanaV2Pair.sol";
import { IKatanaV2Pair } from "@katana/v3-contracts/periphery/interfaces/IKatanaV2Pair.sol";

/// @title Katana v2 Helper Library
/// @notice Calculates the recipient address for a command
2 changes: 1 addition & 1 deletion src/aggregate-router/modules/katana/v2/V2SwapRouter.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.17;

import { IKatanaV2Pair } from "../../../interfaces/external/IKatanaV2Pair.sol";
import { IKatanaV2Pair } from "@katana/v3-contracts/periphery/interfaces/IKatanaV2Pair.sol";
import { KatanaV2Library } from "./KatanaV2Library.sol";
import { KatanaImmutables } from "../KatanaImmutables.sol";
import { Payments } from "../../Payments.sol";
353 changes: 353 additions & 0 deletions src/governance/KatanaGovernance.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import { IKatanaV2Factory } from "./interfaces/IKatanaV2Factory.sol";
import { IKatanaV2Pair } from "@katana/v3-contracts/periphery/interfaces/IKatanaV2Pair.sol";
import { IKatanaGovernance } from "@katana/v3-contracts/external/interfaces/IKatanaGovernance.sol";

contract KatanaGovernance is OwnableUpgradeable, IKatanaV2Factory, IKatanaGovernance {
using EnumerableSet for EnumerableSet.AddressSet;

/// @inheritdoc IKatanaGovernance
address public immutable getPositionManager;

/// @dev Revert error when the length of the array is invalid.
error InvalidLength();
/// @dev Revert error when the caller is not authorized.
error Unauthorized();

/// @dev Gap for upgradeability.
uint256[50] private __gap;

/// @dev Indicates the token is unauthorized for trade.
uint40 private constant UNAUTHORIZED = 0;
/// @dev Indicates the token is publicly allowed for trade.
uint40 private constant AUTHORIZED = type(uint40).max;

/// @dev The factory contract.
IKatanaV2Factory private _factory;
/// @dev The mapping of token to permission.
mapping(address token => Permission) private _permission;
/// @dev The unique set of tokens.
EnumerableSet.AddressSet private _tokens;
/// @dev The router address
address private _router;

/// @dev Only use this modifier for boolean-returned methods
modifier skipIfAllowedAllOrOwner(address account) {
_skipIfAllowedAllOrOwner(account);
_;
}

constructor(address nonfungiblePositionManager) {
getPositionManager = nonfungiblePositionManager;
_disableInitializers();
}

function initialize(address admin, address factory) external initializer {
_setFactory(factory);
__Ownable_init_unchained(admin);

IKatanaV2Pair pair;
uint40 until = AUTHORIZED;
bool[] memory statusesPlaceHolder;
address[] memory allowedPlaceHolder;
uint256 length = IKatanaV2Factory(factory).allPairsLength();

for (uint256 i; i < length; ++i) {
pair = IKatanaV2Pair(IKatanaV2Factory(factory).allPairs(i));
_setPermission(pair.token0(), until, allowedPlaceHolder, statusesPlaceHolder);
_setPermission(pair.token1(), until, allowedPlaceHolder, statusesPlaceHolder);
}
}

function initializeV2(address router) external reinitializer(2) {
_router = router;
}

/// @inheritdoc IKatanaGovernance
function setRouter(address router) external onlyOwner {
_router = router;
}

/**
* @inheritdoc IKatanaV2Factory
*/
function createPair(address tokenA, address tokenB) external returns (address pair) {
address sender = _msgSender();
address[] memory tokens = new address[](2);
tokens[0] = tokenA;
tokens[1] = tokenB;
if (!this.isAuthorized(tokens, sender)) revert Unauthorized();

pair = _factory.createPair(tokenA, tokenB);
}

/**
* @inheritdoc IKatanaGovernance
*/
function createPairAndSetPermission(
address tokenA,
address tokenB,
uint40 whitelistUntil,
address[] calldata alloweds,
bool[] calldata statuses
) external onlyOwner returns (address pair) {
pair = _factory.createPair(tokenA, tokenB);
_setPermission(tokenA, whitelistUntil, alloweds, statuses);
_setPermission(tokenB, whitelistUntil, alloweds, statuses);
}

/**
* @inheritdoc IKatanaGovernance
*/
function setPermission(address token, uint40 whitelistUntil, address[] calldata alloweds, bool[] calldata statuses)
external
onlyOwner
{
_setPermission(token, whitelistUntil, alloweds, statuses);
}

/**
* @inheritdoc IKatanaV2Factory
*/
function setPairImplementation(address impl) external onlyOwner {
_factory.setPairImplementation(impl);
}

/**
* @inheritdoc IKatanaV2Factory
*/
function setAllowedAll(bool shouldAllow) external onlyOwner {
_factory.setAllowedAll(shouldAllow);
}

/**
* @inheritdoc IKatanaGovernance
*/
function setFactory(address factory) external onlyOwner {
_setFactory(factory);
}

/**
* @inheritdoc IKatanaV2Factory
*/
function setTreasury(address newTreasury) external onlyOwner {
_factory.setTreasury(newTreasury);
}

/**
* @inheritdoc IKatanaV2Factory
*/
function getPair(address tokenA, address tokenB) external view returns (address pair) {
return _factory.getPair(tokenA, tokenB);
}

/**
* @inheritdoc IKatanaV2Factory
*/
function allPairs(uint256 index) external view returns (address pair) {
return _factory.allPairs(index);
}

/**
* @inheritdoc IKatanaV2Factory
*/
function allPairsLength() external view returns (uint256) {
return _factory.allPairsLength();
}

/**
* @inheritdoc IKatanaV2Factory
*/
function treasury() external view returns (address) {
return _factory.treasury();
}

/**
* @inheritdoc IKatanaV2Factory
*/
function pairImplementation() external view returns (address) {
return _factory.pairImplementation();
}

/**
* @inheritdoc IKatanaV2Factory
*/
function INIT_CODE_PAIR_HASH() external view returns (bytes32) {
return _factory.INIT_CODE_PAIR_HASH();
}

/**
* @inheritdoc IKatanaV2Factory
*/
function getRouter() external view returns (address) {
return _router;
}

/**
* @inheritdoc IKatanaGovernance
*/
function getFactory() external view returns (address) {
return address(_factory);
}

/**
* @inheritdoc IKatanaGovernance
*/
function isAuthorized(address token, address account)
external
view
skipIfAllowedAllOrOwner(account)
returns (bool authorized)
{
authorized = _isAuthorized(_permission[token], account);
}

/**
* @inheritdoc IKatanaGovernance
*/
function isAuthorized(address[] calldata tokens, address account)
external
view
skipIfAllowedAllOrOwner(account)
returns (bool authorized)
{
uint256 length = tokens.length;

for (uint256 i; i < length; ++i) {
if (!_isAuthorized(_permission[tokens[i]], account)) return false;
}

return true;
}

/**
* @inheritdoc IKatanaGovernance
*/
function getWhitelistUntil(address token) external view returns (uint40) {
return _permission[token].whitelistUntil;
}

/**
* @inheritdoc IKatanaGovernance
*/
function getWhitelistedTokensFor(address account)
external
view
returns (address[] memory tokens, uint40[] memory whitelistUntils)
{
unchecked {
uint256 length = _tokens.length();
tokens = new address[](length);
whitelistUntils = new uint40[](length);
uint256 count;
address token;
uint40 whitelistUntil;
Permission storage $;

for (uint256 i; i < length; ++i) {
token = _tokens.at(i);
$ = _permission[token];
whitelistUntil = $.whitelistUntil;

if (block.timestamp < whitelistUntil && $.allowed[account]) {
tokens[count] = token;
whitelistUntils[count] = whitelistUntil;
++count;
}
}

assembly {
mstore(tokens, count)
mstore(whitelistUntils, count)
}
}
}

/**
* @inheritdoc IKatanaGovernance
*/
function getManyTokensWhitelistInfo()
external
view
returns (address[] memory tokens, uint40[] memory whitelistedUntils)
{
tokens = _tokens.values();
uint256 length = tokens.length;
whitelistedUntils = new uint40[](length);

for (uint256 i; i < length; ++i) {
whitelistedUntils[i] = _permission[tokens[i]].whitelistUntil;
}
}

/**
* @inheritdoc IKatanaV2Factory
*/
function allowedAll() public view returns (bool) {
return _factory.allowedAll();
}

/**
* @dev Sets the address of the factory contract.
* Can only be called by the contract owner.
*/
function _setFactory(address factory) private {
_factory = IKatanaV2Factory(factory);

emit FactoryUpdated(_msgSender(), factory);
}

/**
* @dev Sets the permission for a token.
* @param token The address of the token.
* @param whitelistUntil The end of the whitelist duration in seconds.
* @param alloweds The array of addresses to be allowed in whitelist duration.
* @param statuses The corresponding array of statuses (whether allowed or not).
*/
function _setPermission(address token, uint40 whitelistUntil, address[] memory alloweds, bool[] memory statuses)
private
{
uint256 length = alloweds.length;
if (length != statuses.length) revert InvalidLength();

Permission storage $ = _permission[token];
$.whitelistUntil = whitelistUntil;
_tokens.add(token);

for (uint256 i; i < length; ++i) {
$.allowed[alloweds[i]] = statuses[i];
}

emit PermissionUpdated(_msgSender(), token, whitelistUntil, alloweds, statuses);
}

/**
* @dev Checks if an account is authorized.
* @param account The address of the account to check authorization for.
* @return A boolean indicating whether the account is authorized or not.
*/
function _isAuthorized(Permission storage $, address account) private view returns (bool) {
uint256 expiry = $.whitelistUntil;
if (expiry == UNAUTHORIZED) return false;
if (expiry == AUTHORIZED || block.timestamp > expiry) return true;

return $.allowed[account];
}

/**
* @dev Skips the function if the caller is allowed all or the owner.
* WARNING: This function can return and exit current context and skip the function.
*/
function _skipIfAllowedAllOrOwner(address account) internal view {
if (allowedAll() || account == owner()) {
assembly ("memory-safe") {
mstore(0x0, true)
return(0x0, returndatasize())
}
}
}
}
95 changes: 95 additions & 0 deletions src/governance/interfaces/IKatanaV2Factory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.17 <0.9.0;

/**
* @title IKatanaFactory
*
* @dev IKatanaFactory interface.
* @notice Imported from https://github.com/axieinfinity/contract-infinity/blob/main/contracts/interfaces/IKatanaFactory.sol
*/
interface IKatanaV2Factory {
/**
* @dev Emitted when a pair for `token0` token and `token1` token is created.
*/
event PairCreated(address indexed token0, address indexed token1, address pair, uint256 allPairsLength);

/**
* @dev Emitted when pair implement is changed from `old` to `new`.
*/
event PairProxyUpdated(address indexed newImpl, address indexed oldImpl);

function INIT_CODE_PAIR_HASH() external view returns (bytes32);

/**
* @dev Flag whether allowed all users to call.
*/
function allowedAll() external view returns (bool);

/**
*
* @dev Set allowed all.
*
* Requirements:
*
* - The method caller is admin.
*
*/
function setAllowedAll(bool) external;

/**
* @dev Returns implementation address for pair token.
*/
function pairImplementation() external view returns (address);

/**
* @dev Set implementation address for all pairs.
*
* Requirements:
*
* - The method caller is admin.
*
* Emit a {PairProxyUpdated} event.
*/
function setPairImplementation(address) external;

/**
* @dev Returns treasury address.
*/
function treasury() external view returns (address);

/**
* @dev Sets treasury address.
*
* Requirements:
*
* - The method caller is admin.
*
*/
function setTreasury(address addr) external;

/**
* @dev Returns pair address for `tokenA` and `tokenB`.
*/
function getPair(address tokenA, address tokenB) external view returns (address pair);

/**
* @dev Returns pair address at `index` position.
*/
function allPairs(uint256 index) external view returns (address pair);

/**
* @dev Returns all pairs length.
*/
function allPairsLength() external view returns (uint256);

/**
* @dev Create pair.
*
* Requirements:
*
* - The default method caller is contract admin.
* - All addresses is allowed if `allowedAll` is true.
*
*/
function createPair(address tokenA, address tokenB) external returns (address pair);
}

0 comments on commit f4ea030

Please sign in to comment.