github.com/diadata-org/diadata@v1.4.593/pkg/dia/scraper/exchange-scrapers/uniswap/uniswapV2.sol (about) 1 /** 2 *Submitted for verification at Etherscan.io on 2020-05-05 3 */ 4 5 // File: contracts/interfaces/IUniswapV2Pair.sol 6 7 pragma solidity >=0.5.0; 8 9 interface IUniswapV2Pair { 10 event Approval(address indexed owner, address indexed spender, uint value); 11 event Transfer(address indexed from, address indexed to, uint value); 12 13 function name() external pure returns (string memory); 14 function symbol() external pure returns (string memory); 15 function decimals() external pure returns (uint8); 16 function totalSupply() external view returns (uint); 17 function balanceOf(address owner) external view returns (uint); 18 function allowance(address owner, address spender) external view returns (uint); 19 20 function approve(address spender, uint value) external returns (bool); 21 function transfer(address to, uint value) external returns (bool); 22 function transferFrom(address from, address to, uint value) external returns (bool); 23 24 function DOMAIN_SEPARATOR() external view returns (bytes32); 25 function PERMIT_TYPEHASH() external pure returns (bytes32); 26 function nonces(address owner) external view returns (uint); 27 28 function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 29 30 event Mint(address indexed sender, uint amount0, uint amount1); 31 event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 32 event Swap( 33 address indexed sender, 34 uint amount0In, 35 uint amount1In, 36 uint amount0Out, 37 uint amount1Out, 38 address indexed to 39 ); 40 event Sync(uint112 reserve0, uint112 reserve1); 41 42 function MINIMUM_LIQUIDITY() external pure returns (uint); 43 function factory() external view returns (address); 44 function token0() external view returns (address); 45 function token1() external view returns (address); 46 function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); 47 function price0CumulativeLast() external view returns (uint); 48 function price1CumulativeLast() external view returns (uint); 49 function kLast() external view returns (uint); 50 51 function mint(address to) external returns (uint liquidity); 52 function burn(address to) external returns (uint amount0, uint amount1); 53 function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; 54 function skim(address to) external; 55 function sync() external; 56 57 function initialize(address, address) external; 58 } 59 60 // File: contracts/interfaces/IUniswapV2ERC20.sol 61 62 pragma solidity >=0.5.0; 63 64 interface IUniswapV2ERC20 { 65 event Approval(address indexed owner, address indexed spender, uint value); 66 event Transfer(address indexed from, address indexed to, uint value); 67 68 function name() external pure returns (string memory); 69 function symbol() external pure returns (string memory); 70 function decimals() external pure returns (uint8); 71 function totalSupply() external view returns (uint); 72 function balanceOf(address owner) external view returns (uint); 73 function allowance(address owner, address spender) external view returns (uint); 74 75 function approve(address spender, uint value) external returns (bool); 76 function transfer(address to, uint value) external returns (bool); 77 function transferFrom(address from, address to, uint value) external returns (bool); 78 79 function DOMAIN_SEPARATOR() external view returns (bytes32); 80 function PERMIT_TYPEHASH() external pure returns (bytes32); 81 function nonces(address owner) external view returns (uint); 82 83 function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; 84 } 85 86 // File: contracts/libraries/SafeMath.sol 87 88 pragma solidity =0.5.16; 89 90 // a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math) 91 92 library SafeMath { 93 function add(uint x, uint y) internal pure returns (uint z) { 94 require((z = x + y) >= x, 'ds-math-add-overflow'); 95 } 96 97 function sub(uint x, uint y) internal pure returns (uint z) { 98 require((z = x - y) <= x, 'ds-math-sub-underflow'); 99 } 100 101 function mul(uint x, uint y) internal pure returns (uint z) { 102 require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow'); 103 } 104 } 105 106 // File: contracts/UniswapV2ERC20.sol 107 108 pragma solidity =0.5.16; 109 110 111 112 contract UniswapV2ERC20 is IUniswapV2ERC20 { 113 using SafeMath for uint; 114 115 string public constant name = 'Uniswap V2'; 116 string public constant symbol = 'UNI-V2'; 117 uint8 public constant decimals = 18; 118 uint public totalSupply; 119 mapping(address => uint) public balanceOf; 120 mapping(address => mapping(address => uint)) public allowance; 121 122 bytes32 public DOMAIN_SEPARATOR; 123 // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); 124 bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; 125 mapping(address => uint) public nonces; 126 127 event Approval(address indexed owner, address indexed spender, uint value); 128 event Transfer(address indexed from, address indexed to, uint value); 129 130 constructor() public { 131 uint chainId; 132 assembly { 133 chainId := chainid 134 } 135 DOMAIN_SEPARATOR = keccak256( 136 abi.encode( 137 keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), 138 keccak256(bytes(name)), 139 keccak256(bytes('1')), 140 chainId, 141 address(this) 142 ) 143 ); 144 } 145 146 function _mint(address to, uint value) internal { 147 totalSupply = totalSupply.add(value); 148 balanceOf[to] = balanceOf[to].add(value); 149 emit Transfer(address(0), to, value); 150 } 151 152 function _burn(address from, uint value) internal { 153 balanceOf[from] = balanceOf[from].sub(value); 154 totalSupply = totalSupply.sub(value); 155 emit Transfer(from, address(0), value); 156 } 157 158 function _approve(address owner, address spender, uint value) private { 159 allowance[owner][spender] = value; 160 emit Approval(owner, spender, value); 161 } 162 163 function _transfer(address from, address to, uint value) private { 164 balanceOf[from] = balanceOf[from].sub(value); 165 balanceOf[to] = balanceOf[to].add(value); 166 emit Transfer(from, to, value); 167 } 168 169 function approve(address spender, uint value) external returns (bool) { 170 _approve(msg.sender, spender, value); 171 return true; 172 } 173 174 function transfer(address to, uint value) external returns (bool) { 175 _transfer(msg.sender, to, value); 176 return true; 177 } 178 179 function transferFrom(address from, address to, uint value) external returns (bool) { 180 if (allowance[from][msg.sender] != uint(-1)) { 181 allowance[from][msg.sender] = allowance[from][msg.sender].sub(value); 182 } 183 _transfer(from, to, value); 184 return true; 185 } 186 187 function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external { 188 require(deadline >= block.timestamp, 'UniswapV2: EXPIRED'); 189 bytes32 digest = keccak256( 190 abi.encodePacked( 191 '\x19\x01', 192 DOMAIN_SEPARATOR, 193 keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) 194 ) 195 ); 196 address recoveredAddress = ecrecover(digest, v, r, s); 197 require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE'); 198 _approve(owner, spender, value); 199 } 200 } 201 202 // File: contracts/libraries/Math.sol 203 204 pragma solidity =0.5.16; 205 206 // a library for performing various math operations 207 208 library Math { 209 function min(uint x, uint y) internal pure returns (uint z) { 210 z = x < y ? x : y; 211 } 212 213 // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) 214 function sqrt(uint y) internal pure returns (uint z) { 215 if (y > 3) { 216 z = y; 217 uint x = y / 2 + 1; 218 while (x < z) { 219 z = x; 220 x = (y / x + x) / 2; 221 } 222 } else if (y != 0) { 223 z = 1; 224 } 225 } 226 } 227 228 // File: contracts/libraries/UQ112x112.sol 229 230 pragma solidity =0.5.16; 231 232 // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) 233 234 // range: [0, 2**112 - 1] 235 // resolution: 1 / 2**112 236 237 library UQ112x112 { 238 uint224 constant Q112 = 2**112; 239 240 // encode a uint112 as a UQ112x112 241 function encode(uint112 y) internal pure returns (uint224 z) { 242 z = uint224(y) * Q112; // never overflows 243 } 244 245 // divide a UQ112x112 by a uint112, returning a UQ112x112 246 function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { 247 z = x / uint224(y); 248 } 249 } 250 251 // File: contracts/interfaces/IERC20.sol 252 253 pragma solidity >=0.5.0; 254 255 interface IERC20 { 256 event Approval(address indexed owner, address indexed spender, uint value); 257 event Transfer(address indexed from, address indexed to, uint value); 258 259 function name() external view returns (string memory); 260 function symbol() external view returns (string memory); 261 function decimals() external view returns (uint8); 262 function totalSupply() external view returns (uint); 263 function balanceOf(address owner) external view returns (uint); 264 function allowance(address owner, address spender) external view returns (uint); 265 266 function approve(address spender, uint value) external returns (bool); 267 function transfer(address to, uint value) external returns (bool); 268 function transferFrom(address from, address to, uint value) external returns (bool); 269 } 270 271 // File: contracts/interfaces/IUniswapV2Factory.sol 272 273 pragma solidity >=0.5.0; 274 275 interface IUniswapV2Factory { 276 event PairCreated(address indexed token0, address indexed token1, address pair, uint); 277 278 function feeTo() external view returns (address); 279 function feeToSetter() external view returns (address); 280 281 function getPair(address tokenA, address tokenB) external view returns (address pair); 282 function allPairs(uint) external view returns (address pair); 283 function allPairsLength() external view returns (uint); 284 285 function createPair(address tokenA, address tokenB) external returns (address pair); 286 287 function setFeeTo(address) external; 288 function setFeeToSetter(address) external; 289 } 290 291 // File: contracts/interfaces/IUniswapV2Callee.sol 292 293 pragma solidity >=0.5.0; 294 295 interface IUniswapV2Callee { 296 function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external; 297 } 298 299 // File: contracts/UniswapV2Pair.sol 300 301 pragma solidity =0.5.16; 302 303 304 305 306 307 308 309 310 contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 { 311 using SafeMath for uint; 312 using UQ112x112 for uint224; 313 314 uint public constant MINIMUM_LIQUIDITY = 10**3; 315 bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)'))); 316 317 address public factory; 318 address public token0; 319 address public token1; 320 321 uint112 private reserve0; // uses single storage slot, accessible via getReserves 322 uint112 private reserve1; // uses single storage slot, accessible via getReserves 323 uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves 324 325 uint public price0CumulativeLast; 326 uint public price1CumulativeLast; 327 uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event 328 329 uint private unlocked = 1; 330 modifier lock() { 331 require(unlocked == 1, 'UniswapV2: LOCKED'); 332 unlocked = 0; 333 _; 334 unlocked = 1; 335 } 336 337 function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { 338 _reserve0 = reserve0; 339 _reserve1 = reserve1; 340 _blockTimestampLast = blockTimestampLast; 341 } 342 343 function _safeTransfer(address token, address to, uint value) private { 344 (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value)); 345 require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED'); 346 } 347 348 event Mint(address indexed sender, uint amount0, uint amount1); 349 event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); 350 event Swap( 351 address indexed sender, 352 uint amount0In, 353 uint amount1In, 354 uint amount0Out, 355 uint amount1Out, 356 address indexed to 357 ); 358 event Sync(uint112 reserve0, uint112 reserve1); 359 360 constructor() public { 361 factory = msg.sender; 362 } 363 364 // called once by the factory at time of deployment 365 function initialize(address _token0, address _token1) external { 366 require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check 367 token0 = _token0; 368 token1 = _token1; 369 } 370 371 // update reserves and, on the first call per block, price accumulators 372 function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private { 373 require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW'); 374 uint32 blockTimestamp = uint32(block.timestamp % 2**32); 375 uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired 376 if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { 377 // * never overflows, and + overflow is desired 378 price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed; 379 price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed; 380 } 381 reserve0 = uint112(balance0); 382 reserve1 = uint112(balance1); 383 blockTimestampLast = blockTimestamp; 384 emit Sync(reserve0, reserve1); 385 } 386 387 // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) 388 function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) { 389 address feeTo = IUniswapV2Factory(factory).feeTo(); 390 feeOn = feeTo != address(0); 391 uint _kLast = kLast; // gas savings 392 if (feeOn) { 393 if (_kLast != 0) { 394 uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1)); 395 uint rootKLast = Math.sqrt(_kLast); 396 if (rootK > rootKLast) { 397 uint numerator = totalSupply.mul(rootK.sub(rootKLast)); 398 uint denominator = rootK.mul(5).add(rootKLast); 399 uint liquidity = numerator / denominator; 400 if (liquidity > 0) _mint(feeTo, liquidity); 401 } 402 } 403 } else if (_kLast != 0) { 404 kLast = 0; 405 } 406 } 407 408 // this low-level function should be called from a contract which performs important safety checks 409 function mint(address to) external lock returns (uint liquidity) { 410 (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 411 uint balance0 = IERC20(token0).balanceOf(address(this)); 412 uint balance1 = IERC20(token1).balanceOf(address(this)); 413 uint amount0 = balance0.sub(_reserve0); 414 uint amount1 = balance1.sub(_reserve1); 415 416 bool feeOn = _mintFee(_reserve0, _reserve1); 417 uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee 418 if (_totalSupply == 0) { 419 liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY); 420 _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens 421 } else { 422 liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1); 423 } 424 require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED'); 425 _mint(to, liquidity); 426 427 _update(balance0, balance1, _reserve0, _reserve1); 428 if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date 429 emit Mint(msg.sender, amount0, amount1); 430 } 431 432 // this low-level function should be called from a contract which performs important safety checks 433 function burn(address to) external lock returns (uint amount0, uint amount1) { 434 (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 435 address _token0 = token0; // gas savings 436 address _token1 = token1; // gas savings 437 uint balance0 = IERC20(_token0).balanceOf(address(this)); 438 uint balance1 = IERC20(_token1).balanceOf(address(this)); 439 uint liquidity = balanceOf[address(this)]; 440 441 bool feeOn = _mintFee(_reserve0, _reserve1); 442 uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee 443 amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution 444 amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution 445 require(amount0 > 0 && amount1 > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED'); 446 _burn(address(this), liquidity); 447 _safeTransfer(_token0, to, amount0); 448 _safeTransfer(_token1, to, amount1); 449 balance0 = IERC20(_token0).balanceOf(address(this)); 450 balance1 = IERC20(_token1).balanceOf(address(this)); 451 452 _update(balance0, balance1, _reserve0, _reserve1); 453 if (feeOn) kLast = uint(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date 454 emit Burn(msg.sender, amount0, amount1, to); 455 } 456 457 // this low-level function should be called from a contract which performs important safety checks 458 function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock { 459 require(amount0Out > 0 || amount1Out > 0, 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT'); 460 (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings 461 require(amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY'); 462 463 uint balance0; 464 uint balance1; 465 { // scope for _token{0,1}, avoids stack too deep errors 466 address _token0 = token0; 467 address _token1 = token1; 468 require(to != _token0 && to != _token1, 'UniswapV2: INVALID_TO'); 469 if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens 470 if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens 471 if (data.length > 0) IUniswapV2Callee(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data); 472 balance0 = IERC20(_token0).balanceOf(address(this)); 473 balance1 = IERC20(_token1).balanceOf(address(this)); 474 } 475 uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0; 476 uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0; 477 require(amount0In > 0 || amount1In > 0, 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT'); 478 { // scope for reserve{0,1}Adjusted, avoids stack too deep errors 479 uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3)); 480 uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3)); 481 require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'UniswapV2: K'); 482 } 483 484 _update(balance0, balance1, _reserve0, _reserve1); 485 emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); 486 } 487 488 // force balances to match reserves 489 function skim(address to) external lock { 490 address _token0 = token0; // gas savings 491 address _token1 = token1; // gas savings 492 _safeTransfer(_token0, to, IERC20(_token0).balanceOf(address(this)).sub(reserve0)); 493 _safeTransfer(_token1, to, IERC20(_token1).balanceOf(address(this)).sub(reserve1)); 494 } 495 496 // force reserves to match balances 497 function sync() external lock { 498 _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)), reserve0, reserve1); 499 } 500 }