@@ -16,6 +16,7 @@ contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
1616 bytes4 private constant SELECTOR = bytes4 (keccak256 (bytes ('transfer(address,uint256) ' )));
1717
1818 address public factory;
19+ address public base;
1920 address public token0;
2021 address public token1;
2122
@@ -46,156 +47,88 @@ contract UniswapV2Pair is IUniswapV2Pair, UniswapV2ERC20 {
4647 require (success && (data.length == 0 || abi.decode (data, (bool ))), 'UniswapV2: TRANSFER_FAILED ' );
4748 }
4849
49- event Mint (address indexed sender , uint amount0 , uint amount1 );
50- event Burn (address indexed sender , uint amount0 , uint amount1 , address indexed to );
51- event Swap (
52- address indexed sender ,
53- uint amount0In ,
54- uint amount1In ,
55- uint amount0Out ,
56- uint amount1Out ,
57- address indexed to
58- );
59- event Sync (uint112 reserve0 , uint112 reserve1 );
50+ // event Mint(address indexed sender, uint amount0, uint amount1);
51+ // event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
52+ // event Swap(
53+ // address indexed sender,
54+ // uint amount0In,
55+ // uint amount1In,
56+ // uint amount0Out,
57+ // uint amount1Out,
58+ // address indexed to
59+ // );
60+ // event Sync(uint112 reserve0, uint112 reserve1);
6061
6162 constructor () public {
62- factory = msg .sender ;
63+ // factory = msg.sender;
64+ }
65+
66+ function setFactoryAndBase (address _factory , address _base ) external {
67+ require (factory == address (0 ), "factory already set " );
68+ require (base == address (0 ), "base already set " );
69+ factory = _factory;
70+ base = _base;
71+ bytes memory args = abi.encodeWithSignature (
72+ "setFactoryAndBase(address,address) " ,
73+ _factory,
74+ _base
75+ );
76+ (, bytes memory result ) = base.delegatecall (args);
77+ return abi.decode (result, ());
6378 }
6479
6580 // called once by the factory at time of deployment
6681 function initialize (address _token0 , address _token1 ) external {
67- require (msg .sender == factory, 'UniswapV2: FORBIDDEN ' ); // sufficient check
82+ // require(msg.sender == factory, 'UniswapV2: FORBIDDEN'); // sufficient check
6883 token0 = _token0;
6984 token1 = _token1;
85+ bytes memory args = abi.encodeWithSignature (
86+ "initialize(address,address) " ,
87+ _token0,
88+ _token1
89+ );
90+ (, bytes memory result ) = base.delegatecall (args);
91+ return abi.decode (result, ());
7092 }
7193
72- // update reserves and, on the first call per block, price accumulators
73- function _update (uint balance0 , uint balance1 , uint112 _reserve0 , uint112 _reserve1 ) private {
74- require (balance0 <= uint112 (- 1 ) && balance1 <= uint112 (- 1 ), 'UniswapV2: OVERFLOW ' );
75- uint32 blockTimestamp = uint32 (block .timestamp % 2 ** 32 );
76- uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
77- if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0 ) {
78- // * never overflows, and + overflow is desired
79- price0CumulativeLast += uint (UQ112x112.encode (_reserve1).uqdiv (_reserve0)) * timeElapsed;
80- price1CumulativeLast += uint (UQ112x112.encode (_reserve0).uqdiv (_reserve1)) * timeElapsed;
81- }
82- reserve0 = uint112 (balance0);
83- reserve1 = uint112 (balance1);
84- blockTimestampLast = blockTimestamp;
85- emit Sync (reserve0, reserve1);
86- }
87-
88- // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
89- function _mintFee (uint112 _reserve0 , uint112 _reserve1 ) private returns (bool feeOn ) {
90- address feeTo = IUniswapV2Factory (factory).feeTo ();
91- feeOn = feeTo != address (0 );
92- uint _kLast = kLast; // gas savings
93- if (feeOn) {
94- if (_kLast != 0 ) {
95- uint rootK = Math.sqrt (uint (_reserve0).mul (_reserve1));
96- uint rootKLast = Math.sqrt (_kLast);
97- if (rootK > rootKLast) {
98- uint numerator = totalSupply.mul (rootK.sub (rootKLast));
99- uint denominator = rootK.mul (5 ).add (rootKLast);
100- uint liquidity = numerator / denominator;
101- if (liquidity > 0 ) _mint (feeTo, liquidity);
102- }
103- }
104- } else if (_kLast != 0 ) {
105- kLast = 0 ;
106- }
107- }
108-
109- // this low-level function should be called from a contract which performs important safety checks
110- function mint (address to ) external lock returns (uint liquidity ) {
111- (uint112 _reserve0 , uint112 _reserve1 ,) = getReserves (); // gas savings
112- uint balance0 = IERC20 (token0).balanceOf (address (this ));
113- uint balance1 = IERC20 (token1).balanceOf (address (this ));
114- uint amount0 = balance0.sub (_reserve0);
115- uint amount1 = balance1.sub (_reserve1);
116-
117- bool feeOn = _mintFee (_reserve0, _reserve1);
118- uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
119- if (_totalSupply == 0 ) {
120- liquidity = Math.sqrt (amount0.mul (amount1)).sub (MINIMUM_LIQUIDITY);
121- _mint (address (0 ), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
122- } else {
123- liquidity = Math.min (amount0.mul (_totalSupply) / _reserve0, amount1.mul (_totalSupply) / _reserve1);
124- }
125- require (liquidity > 0 , 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED ' );
126- _mint (to, liquidity);
127-
128- _update (balance0, balance1, _reserve0, _reserve1);
129- if (feeOn) kLast = uint (reserve0).mul (reserve1); // reserve0 and reserve1 are up-to-date
130- emit Mint (msg .sender , amount0, amount1);
94+ function mint (address to ) external returns (uint liquidity ) {
95+ bytes memory args = abi.encodeWithSignature ("mint(address) " , to);
96+ (, bytes memory result ) = base.delegatecall (args);
97+ return abi.decode (result, (uint ));
13198 }
13299
133- // this low-level function should be called from a contract which performs important safety checks
134- function burn (address to ) external lock returns (uint amount0 , uint amount1 ) {
135- (uint112 _reserve0 , uint112 _reserve1 ,) = getReserves (); // gas savings
136- address _token0 = token0; // gas savings
137- address _token1 = token1; // gas savings
138- uint balance0 = IERC20 (_token0).balanceOf (address (this ));
139- uint balance1 = IERC20 (_token1).balanceOf (address (this ));
140- uint liquidity = balanceOf[address (this )];
141-
142- bool feeOn = _mintFee (_reserve0, _reserve1);
143- uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
144- amount0 = liquidity.mul (balance0) / _totalSupply; // using balances ensures pro-rata distribution
145- amount1 = liquidity.mul (balance1) / _totalSupply; // using balances ensures pro-rata distribution
146- require (amount0 > 0 && amount1 > 0 , 'UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED ' );
147- _burn (address (this ), liquidity);
148- _safeTransfer (_token0, to, amount0);
149- _safeTransfer (_token1, to, amount1);
150- balance0 = IERC20 (_token0).balanceOf (address (this ));
151- balance1 = IERC20 (_token1).balanceOf (address (this ));
152-
153- _update (balance0, balance1, _reserve0, _reserve1);
154- if (feeOn) kLast = uint (reserve0).mul (reserve1); // reserve0 and reserve1 are up-to-date
155- emit Burn (msg .sender , amount0, amount1, to);
100+ function burn (address to ) external returns (uint amount0 , uint amount1 ) {
101+ bytes memory args = abi.encodeWithSignature ("burn(address) " , to);
102+ (, bytes memory result ) = base.delegatecall (args);
103+ return abi.decode (result, (uint , uint ));
156104 }
157105
158- // this low-level function should be called from a contract which performs important safety checks
159- function swap (uint amount0Out , uint amount1Out , address to , bytes calldata data ) external lock {
160- require (amount0Out > 0 || amount1Out > 0 , 'UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT ' );
161- (uint112 _reserve0 , uint112 _reserve1 ,) = getReserves (); // gas savings
162- require (amount0Out < _reserve0 && amount1Out < _reserve1, 'UniswapV2: INSUFFICIENT_LIQUIDITY ' );
163-
164- uint balance0;
165- uint balance1;
166- { // scope for _token{0,1}, avoids stack too deep errors
167- address _token0 = token0;
168- address _token1 = token1;
169- require (to != _token0 && to != _token1, 'UniswapV2: INVALID_TO ' );
170- if (amount0Out > 0 ) _safeTransfer (_token0, to, amount0Out); // optimistically transfer tokens
171- if (amount1Out > 0 ) _safeTransfer (_token1, to, amount1Out); // optimistically transfer tokens
172- if (data.length > 0 ) IUniswapV2Callee (to).uniswapV2Call (msg .sender , amount0Out, amount1Out, data);
173- balance0 = IERC20 (_token0).balanceOf (address (this ));
174- balance1 = IERC20 (_token1).balanceOf (address (this ));
175- }
176- uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0 ;
177- uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0 ;
178- require (amount0In > 0 || amount1In > 0 , 'UniswapV2: INSUFFICIENT_INPUT_AMOUNT ' );
179- { // scope for reserve{0,1}Adjusted, avoids stack too deep errors
180- uint balance0Adjusted = balance0.mul (1000 ).sub (amount0In.mul (3 ));
181- uint balance1Adjusted = balance1.mul (1000 ).sub (amount1In.mul (3 ));
182- require (balance0Adjusted.mul (balance1Adjusted) >= uint (_reserve0).mul (_reserve1).mul (1000 ** 2 ), 'UniswapV2: K ' );
183- }
184-
185- _update (balance0, balance1, _reserve0, _reserve1);
186- emit Swap (msg .sender , amount0In, amount1In, amount0Out, amount1Out, to);
106+ function swap (
107+ uint amount0Out ,
108+ uint amount1Out ,
109+ address to ,
110+ bytes calldata data
111+ ) external {
112+ bytes memory args = abi.encodeWithSignature (
113+ "swap(uint256,uint256,address,bytes) " ,
114+ amount0Out,
115+ amount1Out,
116+ to,
117+ data
118+ );
119+ (, bytes memory result ) = base.delegatecall (args);
120+ return abi.decode (result, ());
187121 }
188122
189- // force balances to match reserves
190- function skim (address to ) external lock {
191- address _token0 = token0; // gas savings
192- address _token1 = token1; // gas savings
193- _safeTransfer (_token0, to, IERC20 (_token0).balanceOf (address (this )).sub (reserve0));
194- _safeTransfer (_token1, to, IERC20 (_token1).balanceOf (address (this )).sub (reserve1));
123+ function skim (address to ) external {
124+ bytes memory args = abi.encodeWithSignature ("skim(address) " , to);
125+ (, bytes memory result ) = base.delegatecall (args);
126+ return abi.decode (result, ());
195127 }
196128
197- // force reserves to match balances
198- function sync () external lock {
199- _update (IERC20 (token0).balanceOf (address (this )), IERC20 (token1).balanceOf (address (this )), reserve0, reserve1);
129+ function sync () external {
130+ bytes memory args = abi.encodeWithSignature ("sync() " );
131+ (, bytes memory result ) = base.delegatecall (args);
132+ return abi.decode (result, ());
200133 }
201134}
0 commit comments