Skip to content

Commit

Permalink
Merge pull request #1 from ronin-chain/feature/fork-uniswap-v3
Browse files Browse the repository at this point in the history
feat: fork Uniswap v3
  • Loading branch information
thaixuandang authored Jul 4, 2024
2 parents 8d49db6 + 893bd6a commit 985dcbd
Show file tree
Hide file tree
Showing 99 changed files with 8,663 additions and 6 deletions.
15 changes: 15 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
[submodule "lib/solidity-lib"]
path = lib/solidity-lib
url = https://github.com/Uniswap/solidity-lib
[submodule "lib/base64"]
path = lib/base64
url = https://github.com/Brechtpd/base64
[submodule "lib/v2-core"]
path = lib/v2-core
url = https://github.com/Uniswap/v2-core
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ ffi = true

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

solc = '0.8.23'
solc = '0.7.6'
evm_version = 'istanbul'
use_literal_content = true
extra_output = ["devdoc", "userdoc", "storagelayout"]
Expand Down
1 change: 1 addition & 0 deletions lib/base64
Submodule base64 added at e78d9f
1 change: 1 addition & 0 deletions lib/forge-std
Submodule forge-std added at 07263d
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at 04695a
1 change: 1 addition & 0 deletions lib/solidity-lib
Submodule solidity-lib added at c01640
1 change: 1 addition & 0 deletions lib/v2-core
Submodule v2-core added at 4dd590
10 changes: 5 additions & 5 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1,5 +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/foundry-deployment-kit/lib/openzeppelin-contracts/contracts/
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
@uniswap/lib/contracts/=lib/solidity-lib/contracts/
base64-sol/=lib/base64/
@uniswap/v2-core/contracts=lib/v2-core/contracts/
@uniswap/v3-core/contracts/=src/core
27 changes: 27 additions & 0 deletions src/core/NoDelegateCall.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.7.6;

/// @title Prevents delegatecall to a contract
/// @notice Base contract that provides a modifier for preventing delegatecall to methods in a child contract
abstract contract NoDelegateCall {
/// @dev The original address of this contract
address private immutable original;

constructor() {
// Immutables are computed in the init code of the contract, and then inlined into the deployed bytecode.
// In other words, this variable won't change when it's checked at runtime.
original = address(this);
}

/// @dev Private method is used instead of inlining into modifier because modifiers are copied into each method,
/// and the use of immutable means the address bytes are copied in every place the modifier is used.
function checkNotDelegateCall() private view {
require(address(this) == original);
}

/// @notice Prevents delegatecall into the modified method
modifier noDelegateCall() {
checkNotDelegateCall();
_;
}
}
73 changes: 73 additions & 0 deletions src/core/UniswapV3Factory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity =0.7.6;

import './interfaces/IUniswapV3Factory.sol';

import './UniswapV3PoolDeployer.sol';
import './NoDelegateCall.sol';

import './UniswapV3Pool.sol';

/// @title Canonical Uniswap V3 factory
/// @notice Deploys Uniswap V3 pools and manages ownership and control over pool protocol fees
contract UniswapV3Factory is IUniswapV3Factory, UniswapV3PoolDeployer, NoDelegateCall {
/// @inheritdoc IUniswapV3Factory
address public override owner;

/// @inheritdoc IUniswapV3Factory
mapping(uint24 => int24) public override feeAmountTickSpacing;
/// @inheritdoc IUniswapV3Factory
mapping(address => mapping(address => mapping(uint24 => address))) public override getPool;

constructor() {
owner = msg.sender;
emit OwnerChanged(address(0), msg.sender);

feeAmountTickSpacing[500] = 10;
emit FeeAmountEnabled(500, 10);
feeAmountTickSpacing[3000] = 60;
emit FeeAmountEnabled(3000, 60);
feeAmountTickSpacing[10000] = 200;
emit FeeAmountEnabled(10000, 200);
}

/// @inheritdoc IUniswapV3Factory
function createPool(
address tokenA,
address tokenB,
uint24 fee
) external override noDelegateCall returns (address pool) {
require(tokenA != tokenB);
(address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
require(token0 != address(0));
int24 tickSpacing = feeAmountTickSpacing[fee];
require(tickSpacing != 0);
require(getPool[token0][token1][fee] == address(0));
pool = deploy(address(this), token0, token1, fee, tickSpacing);
getPool[token0][token1][fee] = pool;
// populate mapping in the reverse direction, deliberate choice to avoid the cost of comparing addresses
getPool[token1][token0][fee] = pool;
emit PoolCreated(token0, token1, fee, tickSpacing, pool);
}

/// @inheritdoc IUniswapV3Factory
function setOwner(address _owner) external override {
require(msg.sender == owner);
emit OwnerChanged(owner, _owner);
owner = _owner;
}

/// @inheritdoc IUniswapV3Factory
function enableFeeAmount(uint24 fee, int24 tickSpacing) public override {
require(msg.sender == owner);
require(fee < 1000000);
// 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(feeAmountTickSpacing[fee] == 0);

feeAmountTickSpacing[fee] = tickSpacing;
emit FeeAmountEnabled(fee, tickSpacing);
}
}
Loading

0 comments on commit 985dcbd

Please sign in to comment.