github.com/diadata-org/diadata@v1.4.593/pkg/dia/scraper/exchange-scrapers/velodrome/velodrome.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.0; 3 4 library Clones { 5 /** 6 * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. 7 * 8 * This function uses the create opcode, which should never revert. 9 */ 10 function clone(address implementation) internal returns (address instance) { 11 /// @solidity memory-safe-assembly 12 assembly { 13 // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes 14 // of the `implementation` address with the bytecode before the address. 15 mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) 16 // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. 17 mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) 18 instance := create(0, 0x09, 0x37) 19 } 20 require(instance != address(0), "ERC1167: create failed"); 21 } 22 23 /** 24 * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. 25 * 26 * This function uses the create2 opcode and a `salt` to deterministically deploy 27 * the clone. Using the same `implementation` and `salt` multiple time will revert, since 28 * the clones cannot be deployed twice at the same address. 29 */ 30 function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { 31 /// @solidity memory-safe-assembly 32 assembly { 33 // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes 34 // of the `implementation` address with the bytecode before the address. 35 mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) 36 // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. 37 mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) 38 instance := create2(0, 0x09, 0x37, salt) 39 } 40 require(instance != address(0), "ERC1167: create2 failed"); 41 } 42 43 /** 44 * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. 45 */ 46 function predictDeterministicAddress( 47 address implementation, 48 bytes32 salt, 49 address deployer 50 ) internal pure returns (address predicted) { 51 /// @solidity memory-safe-assembly 52 assembly { 53 let ptr := mload(0x40) 54 mstore(add(ptr, 0x38), deployer) 55 mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) 56 mstore(add(ptr, 0x14), implementation) 57 mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) 58 mstore(add(ptr, 0x58), salt) 59 mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) 60 predicted := keccak256(add(ptr, 0x43), 0x55) 61 } 62 } 63 64 /** 65 * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. 66 */ 67 function predictDeterministicAddress( 68 address implementation, 69 bytes32 salt 70 ) internal view returns (address predicted) { 71 return predictDeterministicAddress(implementation, salt, address(this)); 72 } 73 } 74 75 interface IPoolFactory { 76 event SetFeeManager(address feeManager); 77 event SetPauser(address pauser); 78 event SetPauseState(bool state); 79 event SetVoter(address voter); 80 event PoolCreated(address indexed token0, address indexed token1, bool indexed stable, address pool, uint256); 81 event SetCustomFee(address indexed pool, uint256 fee); 82 83 error FeeInvalid(); 84 error FeeTooHigh(); 85 error InvalidPool(); 86 error NotFeeManager(); 87 error NotPauser(); 88 error NotSinkConverter(); 89 error NotVoter(); 90 error PoolAlreadyExists(); 91 error SameAddress(); 92 error ZeroFee(); 93 error ZeroAddress(); 94 95 /// @notice returns the number of pools created from this factory 96 function allPoolsLength() external view returns (uint256); 97 98 /// @notice Is a valid pool created by this factory. 99 /// @param . 100 function isPool(address pool) external view returns (bool); 101 102 /// @notice Support for Velodrome v1 which wraps around isPool(pool); 103 /// @param . 104 function isPair(address pool) external view returns (bool); 105 106 /// @notice Return address of pool created by this factory 107 /// @param tokenA . 108 /// @param tokenB . 109 /// @param stable True if stable, false if volatile 110 function getPool(address tokenA, address tokenB, bool stable) external view returns (address); 111 112 /// @notice Support for v3-style pools which wraps around getPool(tokenA,tokenB,stable) 113 /// @dev fee is converted to stable boolean. 114 /// @param tokenA . 115 /// @param tokenB . 116 /// @param fee 1 if stable, 0 if volatile, else returns address(0) 117 function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address); 118 119 /// @notice Support for Velodrome v1 pools as a "pool" was previously referenced as "pair" 120 /// @notice Wraps around getPool(tokenA,tokenB,stable) 121 function getPair(address tokenA, address tokenB, bool stable) external view returns (address); 122 123 /// @dev Only called once to set to Voter.sol - Voter does not have a function 124 /// to call this contract method, so once set it's immutable. 125 /// This also follows convention of setVoterAndDistributor() in VotingEscrow.sol 126 /// @param _voter . 127 function setVoter(address _voter) external; 128 129 function setSinkConverter(address _sinkConvert, address _velo, address _veloV2) external; 130 131 function setPauser(address _pauser) external; 132 133 function setPauseState(bool _state) external; 134 135 function setFeeManager(address _feeManager) external; 136 137 /// @notice Set default fee for stable and volatile pools. 138 /// @dev Throws if higher than maximum fee. 139 /// Throws if fee is zero. 140 /// @param _stable Stable or volatile pool. 141 /// @param _fee . 142 function setFee(bool _stable, uint256 _fee) external; 143 144 /// @notice Set overriding fee for a pool from the default 145 /// @dev A custom fee of zero means the default fee will be used. 146 function setCustomFee(address _pool, uint256 _fee) external; 147 148 /// @notice Returns fee for a pool, as custom fees are possible. 149 function getFee(address _pool, bool _stable) external view returns (uint256); 150 151 /// @notice Create a pool given two tokens and if they're stable/volatile 152 /// @dev token order does not matter 153 /// @param tokenA . 154 /// @param tokenB . 155 /// @param stable . 156 function createPool(address tokenA, address tokenB, bool stable) external returns (address pool); 157 158 /// @notice Support for v3-style pools which wraps around createPool(tokena,tokenB,stable) 159 /// @dev fee is converted to stable boolean 160 /// @dev token order does not matter 161 /// @param tokenA . 162 /// @param tokenB . 163 /// @param fee 1 if stable, 0 if volatile, else revert 164 function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool); 165 166 /// @notice Support for Velodrome v1 which wraps around createPool(tokenA,tokenB,stable) 167 function createPair(address tokenA, address tokenB, bool stable) external returns (address pool); 168 169 function isPaused() external view returns (bool); 170 171 function velo() external view returns (address); 172 173 function veloV2() external view returns (address); 174 175 function voter() external view returns (address); 176 177 function sinkConverter() external view returns (address); 178 179 function implementation() external view returns (address); 180 } 181 182 contract PoolFactory is IPoolFactory { 183 address public immutable implementation; 184 185 bool public isPaused; 186 address public pauser; 187 188 uint256 public stableFee; 189 uint256 public volatileFee; 190 uint256 public constant MAX_FEE = 100; // 1% 191 // Override to indicate there is custom 0% fee - as a 0 value in the customFee mapping indicates 192 // that no custom fee rate has been set 193 uint256 public constant ZERO_FEE_INDICATOR = 420; 194 address public feeManager; 195 196 /// @dev used to change the name/symbol of the pool by calling emergencyCouncil 197 address public voter; 198 199 /// @dev used to enable Router conversion of v1 => v2 VEL0 200 address public velo; 201 address public veloV2; 202 address public sinkConverter; 203 204 mapping(address => mapping(address => mapping(bool => address))) private _getPool; 205 address[] public allPools; 206 mapping(address => bool) private _isPool; // simplified check if its a pool, given that `stable` flag might not be available in peripherals 207 mapping(address => uint256) public customFee; // override for custom fees 208 209 address internal _temp0; 210 address internal _temp1; 211 bool internal _temp; 212 213 constructor(address _implementation) { 214 implementation = _implementation; 215 voter = msg.sender; 216 pauser = msg.sender; 217 feeManager = msg.sender; 218 sinkConverter = msg.sender; 219 isPaused = false; 220 stableFee = 5; // 0.05% 221 volatileFee = 30; // 0.3% 222 } 223 224 /// @inheritdoc IPoolFactory 225 function allPoolsLength() external view returns (uint256) { 226 return allPools.length; 227 } 228 229 /// @inheritdoc IPoolFactory 230 function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address) { 231 return fee > 1 ? address(0) : fee == 1 ? _getPool[tokenA][tokenB][true] : _getPool[tokenA][tokenB][false]; 232 } 233 234 /// @inheritdoc IPoolFactory 235 function getPool(address tokenA, address tokenB, bool stable) external view returns (address) { 236 return _getPool[tokenA][tokenB][stable]; 237 } 238 239 /// @inheritdoc IPoolFactory 240 function getPair(address tokenA, address tokenB, bool stable) external view returns (address) { 241 return _getPool[tokenA][tokenB][stable]; 242 } 243 244 /// @inheritdoc IPoolFactory 245 function isPool(address pool) external view returns (bool) { 246 return _isPool[pool]; 247 } 248 249 /// @inheritdoc IPoolFactory 250 function isPair(address pool) external view returns (bool) { 251 return _isPool[pool]; 252 } 253 254 /// @inheritdoc IPoolFactory 255 function setVoter(address _voter) external { 256 if (msg.sender != voter) revert NotVoter(); 257 voter = _voter; 258 emit SetVoter(_voter); 259 } 260 261 /// @inheritdoc IPoolFactory 262 function setSinkConverter(address _sinkConverter, address _velo, address _veloV2) external { 263 if (msg.sender != sinkConverter) revert NotSinkConverter(); 264 sinkConverter = _sinkConverter; 265 velo = _velo; 266 veloV2 = _veloV2; 267 268 // Follow logic of createPool() - except add getPool values for both volatile 269 // and stable so there is no way to create an additional velo => veloV2 pool 270 (address token0, address token1) = _velo < _veloV2 ? (_velo, _veloV2) : (_veloV2, _velo); 271 _getPool[token0][token1][true] = sinkConverter; 272 _getPool[token1][token0][true] = sinkConverter; 273 _getPool[token0][token1][false] = sinkConverter; 274 _getPool[token1][token0][false] = sinkConverter; 275 allPools.push(sinkConverter); 276 _isPool[sinkConverter] = true; 277 278 // emit two events - for both the "stable" and "volatile" pool being created 279 emit PoolCreated(token0, token1, true, sinkConverter, allPools.length); 280 emit PoolCreated(token0, token1, false, sinkConverter, allPools.length); 281 } 282 283 function setPauser(address _pauser) external { 284 if (msg.sender != pauser) revert NotPauser(); 285 if (_pauser == address(0)) revert ZeroAddress(); 286 pauser = _pauser; 287 emit SetPauser(_pauser); 288 } 289 290 function setPauseState(bool _state) external { 291 if (msg.sender != pauser) revert NotPauser(); 292 isPaused = _state; 293 emit SetPauseState(_state); 294 } 295 296 function setFeeManager(address _feeManager) external { 297 if (msg.sender != feeManager) revert NotFeeManager(); 298 if (_feeManager == address(0)) revert ZeroAddress(); 299 feeManager = _feeManager; 300 emit SetFeeManager(_feeManager); 301 } 302 303 /// @inheritdoc IPoolFactory 304 function setFee(bool _stable, uint256 _fee) external { 305 if (msg.sender != feeManager) revert NotFeeManager(); 306 if (_fee > MAX_FEE) revert FeeTooHigh(); 307 if (_fee == 0) revert ZeroFee(); 308 if (_stable) { 309 stableFee = _fee; 310 } else { 311 volatileFee = _fee; 312 } 313 } 314 315 /// @inheritdoc IPoolFactory 316 function setCustomFee(address pool, uint256 fee) external { 317 if (msg.sender != feeManager) revert NotFeeManager(); 318 if (fee > MAX_FEE && fee != ZERO_FEE_INDICATOR) revert FeeTooHigh(); 319 if (!_isPool[pool]) revert InvalidPool(); 320 321 customFee[pool] = fee; 322 emit SetCustomFee(pool, fee); 323 } 324 325 /// @inheritdoc IPoolFactory 326 function getFee(address pool, bool _stable) public view returns (uint256) { 327 uint256 fee = customFee[pool]; 328 return fee == ZERO_FEE_INDICATOR ? 0 : fee != 0 ? fee : _stable ? stableFee : volatileFee; 329 } 330 331 /// @inheritdoc IPoolFactory 332 function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool) { 333 if (fee > 1) revert FeeInvalid(); 334 bool stable = fee == 1; 335 return createPool(tokenA, tokenB, stable); 336 } 337 338 /// @inheritdoc IPoolFactory 339 function createPool(address tokenA, address tokenB, bool stable) public returns (address pool) { 340 if (tokenA == tokenB) revert SameAddress(); 341 (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); 342 if (token0 == address(0)) revert ZeroAddress(); 343 if (_getPool[token0][token1][stable] != address(0)) revert PoolAlreadyExists(); 344 bytes32 salt = keccak256(abi.encodePacked(token0, token1, stable)); // salt includes stable as well, 3 parameters 345 pool = Clones.cloneDeterministic(implementation, salt); 346 IPool(pool).initialize(token0, token1, stable); 347 _getPool[token0][token1][stable] = pool; 348 _getPool[token1][token0][stable] = pool; // populate mapping in the reverse direction 349 allPools.push(pool); 350 _isPool[pool] = true; 351 emit PoolCreated(token0, token1, stable, pool, allPools.length); 352 } 353 354 /// @inheritdoc IPoolFactory 355 function createPair(address tokenA, address tokenB, bool stable) external returns (address pool) { 356 return createPool(tokenA, tokenB, stable); 357 } 358 } 359 360 interface IPool { 361 error DepositsNotEqual(); 362 error BelowMinimumK(); 363 error FactoryAlreadySet(); 364 error InsufficientLiquidity(); 365 error InsufficientLiquidityMinted(); 366 error InsufficientLiquidityBurned(); 367 error InsufficientOutputAmount(); 368 error InsufficientInputAmount(); 369 error IsPaused(); 370 error InvalidTo(); 371 error K(); 372 error NotEmergencyCouncil(); 373 374 event Fees(address indexed sender, uint256 amount0, uint256 amount1); 375 event Mint(address indexed sender, uint256 amount0, uint256 amount1); 376 event Burn(address indexed sender, address indexed to, uint256 amount0, uint256 amount1); 377 event Swap( 378 address indexed sender, 379 address indexed to, 380 uint256 amount0In, 381 uint256 amount1In, 382 uint256 amount0Out, 383 uint256 amount1Out 384 ); 385 event Sync(uint256 reserve0, uint256 reserve1); 386 event Claim(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1); 387 388 function metadata() 389 external 390 view 391 returns (uint256 dec0, uint256 dec1, uint256 r0, uint256 r1, bool st, address t0, address t1); 392 393 function claimFees() external returns (uint256, uint256); 394 395 function tokens() external view returns (address, address); 396 397 function token0() external view returns (address); 398 399 function token1() external view returns (address); 400 401 function stable() external view returns (bool); 402 403 function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external; 404 405 function burn(address to) external returns (uint256 amount0, uint256 amount1); 406 407 function mint(address to) external returns (uint256 liquidity); 408 409 function getReserves() external view returns (uint256 _reserve0, uint256 _reserve1, uint256 _blockTimestampLast); 410 411 function getAmountOut(uint256, address) external view returns (uint256); 412 413 function skim(address to) external; 414 415 function initialize(address _token0, address _token1, bool _stable) external; 416 } 417 418 /** 419 * @dev Interface of the ERC20 standard as defined in the EIP. 420 */ 421 interface IERC20 { 422 /** 423 * @dev Emitted when `value` tokens are moved from one account (`from`) to 424 * another (`to`). 425 * 426 * Note that `value` may be zero. 427 */ 428 event Transfer(address indexed from, address indexed to, uint256 value); 429 430 /** 431 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 432 * a call to {approve}. `value` is the new allowance. 433 */ 434 event Approval(address indexed owner, address indexed spender, uint256 value); 435 436 /** 437 * @dev Returns the amount of tokens in existence. 438 */ 439 function totalSupply() external view returns (uint256); 440 441 /** 442 * @dev Returns the amount of tokens owned by `account`. 443 */ 444 function balanceOf(address account) external view returns (uint256); 445 446 /** 447 * @dev Moves `amount` tokens from the caller's account to `to`. 448 * 449 * Returns a boolean value indicating whether the operation succeeded. 450 * 451 * Emits a {Transfer} event. 452 */ 453 function transfer(address to, uint256 amount) external returns (bool); 454 455 /** 456 * @dev Returns the remaining number of tokens that `spender` will be 457 * allowed to spend on behalf of `owner` through {transferFrom}. This is 458 * zero by default. 459 * 460 * This value changes when {approve} or {transferFrom} are called. 461 */ 462 function allowance(address owner, address spender) external view returns (uint256); 463 464 /** 465 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 466 * 467 * Returns a boolean value indicating whether the operation succeeded. 468 * 469 * IMPORTANT: Beware that changing an allowance with this method brings the risk 470 * that someone may use both the old and the new allowance by unfortunate 471 * transaction ordering. One possible solution to mitigate this race 472 * condition is to first reduce the spender's allowance to 0 and set the 473 * desired value afterwards: 474 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 475 * 476 * Emits an {Approval} event. 477 */ 478 function approve(address spender, uint256 amount) external returns (bool); 479 480 /** 481 * @dev Moves `amount` tokens from `from` to `to` using the 482 * allowance mechanism. `amount` is then deducted from the caller's 483 * allowance. 484 * 485 * Returns a boolean value indicating whether the operation succeeded. 486 * 487 * Emits a {Transfer} event. 488 */ 489 function transferFrom(address from, address to, uint256 amount) external returns (bool); 490 } 491 492 interface IERC20Metadata is IERC20 { 493 /** 494 * @dev Returns the name of the token. 495 */ 496 function name() external view returns (string memory); 497 498 /** 499 * @dev Returns the symbol of the token. 500 */ 501 function symbol() external view returns (string memory); 502 503 /** 504 * @dev Returns the decimals places of the token. 505 */ 506 function decimals() external view returns (uint8); 507 }