-
Notifications
You must be signed in to change notification settings - Fork 504
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
491 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
7158 | ||
7117 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
31728 | ||
31806 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Submodule v4-core
updated
19 files
+0 −100 | LICENSE | |
+1 −7 | README.md | |
+63 −0 | licenses/BUSL_LICENSE | |
+7 −0 | licenses/MIT_LICENSE | |
+1 −1 | src/ProtocolFees.sol | |
+1 −1 | src/interfaces/external/IERC20Minimal.sol | |
+1 −1 | src/libraries/BitMath.sol | |
+1 −1 | src/libraries/FixedPoint128.sol | |
+1 −1 | src/libraries/FixedPoint96.sol | |
+1 −1 | src/libraries/LPFeeLibrary.sol | |
+1 −1 | src/libraries/LiquidityMath.sol | |
+1 −1 | src/libraries/ParseBytes.sol | |
+1 −1 | src/libraries/ProtocolFeeLibrary.sol | |
+1 −1 | src/libraries/SafeCast.sol | |
+1 −1 | src/libraries/SqrtPriceMath.sol | |
+1 −1 | src/libraries/SwapMath.sol | |
+1 −1 | src/libraries/TickMath.sol | |
+1 −1 | src/libraries/UnsafeMath.sol | |
+4 −1 | test/libraries/Pool.t.sol |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// SPADIX-License-Identifier: UNLICENSED | ||
pragma solidity 0.8.26; | ||
|
||
import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; | ||
import {VanityAddressLib} from "./libraries/VanityAddressLib.sol"; | ||
import {IUniswapV4DeployerCompetition} from "./interfaces/IUniswapV4DeployerCompetition.sol"; | ||
|
||
/// @title UniswapV4DeployerCompetition | ||
/// @notice A contract to crowdsource a salt for the best Uniswap V4 address | ||
contract UniswapV4DeployerCompetition is IUniswapV4DeployerCompetition { | ||
using VanityAddressLib for address; | ||
|
||
/// @dev The salt for the best address found so far | ||
bytes32 public bestAddressSalt; | ||
/// @dev The submitter of the best address found so far | ||
address public bestAddressSubmitter; | ||
|
||
/// @dev The deadline for the competition | ||
uint256 public immutable competitionDeadline; | ||
/// @dev The init code hash of the V4 contract | ||
bytes32 public immutable initCodeHash; | ||
|
||
/// @dev The deployer who can initiate the deployment of the v4 PoolManager, until the exclusive deploy deadline. | ||
/// @dev After this deadline anyone can deploy. | ||
address public immutable deployer; | ||
/// @dev The deadline for exclusive deployment by deployer after deadline | ||
uint256 public immutable exclusiveDeployDeadline; | ||
|
||
constructor( | ||
bytes32 _initCodeHash, | ||
uint256 _competitionDeadline, | ||
address _exclusiveDeployer, | ||
uint256 _exclusiveDeployLength | ||
) { | ||
initCodeHash = _initCodeHash; | ||
competitionDeadline = _competitionDeadline; | ||
exclusiveDeployDeadline = _competitionDeadline + _exclusiveDeployLength; | ||
deployer = _exclusiveDeployer; | ||
} | ||
|
||
/// @inheritdoc IUniswapV4DeployerCompetition | ||
function updateBestAddress(bytes32 salt) external { | ||
if (block.timestamp > competitionDeadline) { | ||
revert CompetitionOver(block.timestamp, competitionDeadline); | ||
} | ||
|
||
address saltSubAddress = address(bytes20(salt)); | ||
if (saltSubAddress != msg.sender && saltSubAddress != address(0)) revert InvalidSender(salt, msg.sender); | ||
|
||
address newAddress = Create2.computeAddress(salt, initCodeHash); | ||
address _bestAddress = bestAddress(); | ||
if (!newAddress.betterThan(_bestAddress)) { | ||
revert WorseAddress(newAddress, _bestAddress, newAddress.score(), _bestAddress.score()); | ||
} | ||
|
||
bestAddressSalt = salt; | ||
bestAddressSubmitter = msg.sender; | ||
|
||
emit NewAddressFound(newAddress, msg.sender, newAddress.score()); | ||
} | ||
|
||
/// @inheritdoc IUniswapV4DeployerCompetition | ||
function deploy(bytes memory bytecode) external { | ||
if (keccak256(bytecode) != initCodeHash) { | ||
revert InvalidBytecode(); | ||
} | ||
|
||
if (block.timestamp <= competitionDeadline) { | ||
revert CompetitionNotOver(block.timestamp, competitionDeadline); | ||
} | ||
|
||
if (msg.sender != deployer && block.timestamp <= exclusiveDeployDeadline) { | ||
// anyone can deploy after the deadline | ||
revert NotAllowedToDeploy(msg.sender, deployer); | ||
} | ||
|
||
// the owner of the contract must be encoded in the bytecode | ||
Create2.deploy(0, bestAddressSalt, bytecode); | ||
} | ||
|
||
/// @dev returns the best address found so far | ||
function bestAddress() public view returns (address) { | ||
return Create2.computeAddress(bestAddressSalt, initCodeHash); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// SPADIX-License-Identifier: UNLICENSED | ||
pragma solidity 0.8.26; | ||
|
||
/// @title UniswapV4DeployerCompetition | ||
/// @notice A competition to deploy the UniswapV4 contract with the best address | ||
interface IUniswapV4DeployerCompetition { | ||
event NewAddressFound(address indexed bestAddress, address indexed submitter, uint256 score); | ||
|
||
error InvalidBytecode(); | ||
error CompetitionNotOver(uint256 currentTime, uint256 deadline); | ||
error CompetitionOver(uint256 currentTime, uint256 deadline); | ||
error NotAllowedToDeploy(address sender, address deployer); | ||
error WorseAddress(address newAddress, address bestAddress, uint256 newScore, uint256 bestScore); | ||
error InvalidSender(bytes32 salt, address sender); | ||
|
||
/// @notice Updates the best address if the new address has a better vanity score | ||
/// @param salt The salt to use to compute the new address with CREATE2 | ||
/// @dev The first 20 bytes of the salt must be either address(0) or msg.sender | ||
function updateBestAddress(bytes32 salt) external; | ||
|
||
/// @notice deploys the Uniswap v4 PoolManager contract | ||
/// @param bytecode The bytecode of the Uniswap v4 PoolManager contract | ||
/// @dev The bytecode must match the initCodeHash | ||
function deploy(bytes memory bytecode) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.0; | ||
|
||
/// @title VanityAddressLib | ||
/// @notice A library to score addresses based on their vanity | ||
library VanityAddressLib { | ||
/// @notice Compares two addresses and returns true if the first address has a better vanity score | ||
/// @param first The first address to compare | ||
/// @param second The second address to compare | ||
/// @return better True if the first address has a better vanity score | ||
function betterThan(address first, address second) internal pure returns (bool better) { | ||
return score(first) > score(second); | ||
} | ||
|
||
/// @notice Scores an address based on its vanity | ||
/// @dev Scoring rules: | ||
/// Requirement: The first nonzero nibble must be 4 | ||
/// 10 points for every leading 0 nibble | ||
/// 40 points if the first 4 is followed by 3 more 4s | ||
/// 20 points if the first nibble after the 4 4s is NOT a 4 | ||
/// 20 points if the last 4 nibbles are 4s | ||
/// 1 point for every 4 | ||
/// @param addr The address to score | ||
/// @return calculatedScore The vanity score of the address | ||
function score(address addr) internal pure returns (uint256 calculatedScore) { | ||
// convert the address to bytes for easier parsing | ||
bytes20 addrBytes = bytes20(addr); | ||
|
||
unchecked { | ||
// 10 points per leading zero nibble | ||
uint256 leadingZeroCount = getLeadingNibbleCount(addrBytes, 0, 0); | ||
calculatedScore += (leadingZeroCount * 10); | ||
|
||
// special handling for 4s immediately after leading 0s | ||
uint256 leadingFourCount = getLeadingNibbleCount(addrBytes, leadingZeroCount, 4); | ||
// If the first nonzero nibble is not 4, return 0 | ||
if (leadingFourCount == 0) { | ||
return 0; | ||
} else if (leadingFourCount == 4) { | ||
// 60 points if exactly 4 4s | ||
calculatedScore += 60; | ||
} else if (leadingFourCount > 4) { | ||
// 40 points if more than 4 4s | ||
calculatedScore += 40; | ||
} | ||
|
||
// handling for remaining nibbles | ||
for (uint256 i = 0; i < addrBytes.length * 2; i++) { | ||
uint8 currentNibble = getNibble(addrBytes, i); | ||
|
||
// 1 extra point for any 4 nibbles | ||
if (currentNibble == 4) { | ||
calculatedScore += 1; | ||
} | ||
} | ||
|
||
// If the last 4 nibbles are 4s, add 20 points | ||
if (addrBytes[18] == 0x44 && addrBytes[19] == 0x44) { | ||
calculatedScore += 20; | ||
} | ||
} | ||
} | ||
|
||
/// @notice Returns the number of leading nibbles in an address that match a given value | ||
/// @param addrBytes The address to count the leading zero nibbles in | ||
function getLeadingNibbleCount(bytes20 addrBytes, uint256 startIndex, uint8 comparison) | ||
internal | ||
pure | ||
returns (uint256 count) | ||
{ | ||
if (startIndex >= addrBytes.length * 2) { | ||
return count; | ||
} | ||
|
||
for (uint256 i = startIndex; i < addrBytes.length * 2; i++) { | ||
uint8 currentNibble = getNibble(addrBytes, i); | ||
if (currentNibble != comparison) { | ||
return count; | ||
} | ||
count += 1; | ||
} | ||
} | ||
|
||
/// @notice Returns the nibble at a given index in an address | ||
/// @param input The address to get the nibble from | ||
/// @param nibbleIndex The index of the nibble to get | ||
function getNibble(bytes20 input, uint256 nibbleIndex) internal pure returns (uint8 currentNibble) { | ||
uint8 currByte = uint8(input[nibbleIndex / 2]); | ||
if (nibbleIndex % 2 == 0) { | ||
// Get the higher nibble of the byte | ||
currentNibble = currByte >> 4; | ||
} else { | ||
// Get the lower nibble of the byte | ||
currentNibble = currByte & 0x0F; | ||
} | ||
} | ||
} |
Oops, something went wrong.