MINIMUM_TOTAL_SUPPLY -> MINIMUM_LIQUIDITY (#51)
* MINIMUM_TOTAL_SUPPLY -> MINIMUM_LIQUIDITY make selector private
This commit is contained in:
@ -13,7 +13,6 @@ contract UniswapV2ERC20 is IUniswapV2ERC20 {
|
||||
mapping(address => uint) public balanceOf;
|
||||
mapping(address => mapping(address => uint)) public allowance;
|
||||
|
||||
uint public constant MINIMUM_TOTAL_SUPPLY = 10**4;
|
||||
bytes32 public DOMAIN_SEPARATOR;
|
||||
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
|
||||
bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
|
||||
@ -39,18 +38,14 @@ contract UniswapV2ERC20 is IUniswapV2ERC20 {
|
||||
}
|
||||
|
||||
function _mint(address to, uint value) internal {
|
||||
uint _totalSupply = totalSupply.add(value);
|
||||
require(_totalSupply >= MINIMUM_TOTAL_SUPPLY, 'UniswapV2: MINIMUM_TOTAL_SUPPLY');
|
||||
totalSupply = _totalSupply;
|
||||
totalSupply = totalSupply.add(value);
|
||||
balanceOf[to] = balanceOf[to].add(value);
|
||||
emit Transfer(address(0), to, value);
|
||||
}
|
||||
|
||||
function _burn(address from, uint value) internal {
|
||||
uint _totalSupply = totalSupply.sub(value);
|
||||
require(_totalSupply == 0 || _totalSupply >= MINIMUM_TOTAL_SUPPLY, 'UniswapV2: MINIMUM_TOTAL_SUPPLY');
|
||||
balanceOf[from] = balanceOf[from].sub(value);
|
||||
totalSupply = _totalSupply;
|
||||
totalSupply = totalSupply.sub(value);
|
||||
emit Transfer(from, address(0), value);
|
||||
}
|
||||
|
||||
|
||||
@ -11,7 +11,8 @@ contract UniswapV2Exchange is IUniswapV2Exchange, UniswapV2ERC20 {
|
||||
using SafeMath for uint;
|
||||
using UQ112x112 for uint224;
|
||||
|
||||
bytes4 public constant selector = bytes4(keccak256(bytes('transfer(address,uint256)')));
|
||||
uint public constant MINIMUM_LIQUIDITY = 10**3;
|
||||
bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));
|
||||
|
||||
address public factory;
|
||||
address public token0;
|
||||
@ -42,7 +43,7 @@ contract UniswapV2Exchange is IUniswapV2Exchange, UniswapV2ERC20 {
|
||||
}
|
||||
|
||||
function _safeTransfer(address token, address to, uint value) private {
|
||||
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(selector, to, value));
|
||||
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
|
||||
require(success && (data.length == 0 || abi.decode(data, (bool))), 'UniswapV2: TRANSFER_FAILED');
|
||||
}
|
||||
|
||||
@ -107,9 +108,12 @@ contract UniswapV2Exchange is IUniswapV2Exchange, UniswapV2ERC20 {
|
||||
|
||||
bool feeOn = _mintFee(_reserve0, _reserve1);
|
||||
uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
|
||||
liquidity = _totalSupply == 0
|
||||
? Math.sqrt(amount0.mul(amount1))
|
||||
: Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
|
||||
if (_totalSupply == 0) {
|
||||
liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
|
||||
_mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
|
||||
} else {
|
||||
liquidity = Math.min(amount0.mul(_totalSupply) / _reserve0, amount1.mul(_totalSupply) / _reserve1);
|
||||
}
|
||||
require(liquidity > 0, 'UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED');
|
||||
_mint(to, liquidity);
|
||||
|
||||
|
||||
@ -15,7 +15,6 @@ interface IUniswapV2ERC20 {
|
||||
function transfer(address to, uint value) external returns (bool);
|
||||
function transferFrom(address from, address to, uint value) external returns (bool);
|
||||
|
||||
function MINIMUM_TOTAL_SUPPLY() external pure returns (uint);
|
||||
function DOMAIN_SEPARATOR() external view returns (bytes32);
|
||||
function PERMIT_TYPEHASH() external pure returns (bytes32);
|
||||
function nonces(address owner) external view returns (uint);
|
||||
|
||||
@ -15,7 +15,6 @@ interface IUniswapV2Exchange {
|
||||
function transfer(address to, uint value) external returns (bool);
|
||||
function transferFrom(address from, address to, uint value) external returns (bool);
|
||||
|
||||
function MINIMUM_TOTAL_SUPPLY() external pure returns (uint);
|
||||
function DOMAIN_SEPARATOR() external view returns (bytes32);
|
||||
function PERMIT_TYPEHASH() external pure returns (bytes32);
|
||||
function nonces(address owner) external view returns (uint);
|
||||
@ -27,7 +26,7 @@ interface IUniswapV2Exchange {
|
||||
event Swap(address indexed sender, address indexed tokenIn, uint amountIn, uint amountOut, address indexed to);
|
||||
event Sync(uint112 reserve0, uint112 reserve1);
|
||||
|
||||
function selector() external pure returns (bytes4);
|
||||
function MINIMUM_LIQUIDITY() external pure returns (uint);
|
||||
function factory() external view returns (address);
|
||||
function token0() external view returns (address);
|
||||
function token1() external view returns (address);
|
||||
|
||||
@ -7,6 +7,8 @@ import { expandTo18Decimals, mineBlock, encodePrice } from './shared/utilities'
|
||||
import { exchangeFixture } from './shared/fixtures'
|
||||
import { AddressZero } from 'ethers/constants'
|
||||
|
||||
const MINIMUM_LIQUIDITY = bigNumberify(10).pow(3)
|
||||
|
||||
chai.use(solidity)
|
||||
|
||||
const overrides = {
|
||||
@ -43,14 +45,17 @@ describe('UniswapV2Exchange', () => {
|
||||
const expectedLiquidity = expandTo18Decimals(2)
|
||||
await expect(exchange.mint(wallet.address, overrides))
|
||||
.to.emit(exchange, 'Transfer')
|
||||
.withArgs(AddressZero, wallet.address, expectedLiquidity)
|
||||
.withArgs(AddressZero, AddressZero, MINIMUM_LIQUIDITY)
|
||||
// commented out because of this bug: https://github.com/EthWorks/Waffle/issues/100
|
||||
// .to.emit(exchange, 'Transfer')
|
||||
// .withArgs(AddressZero, wallet.address, expectedLiquidity)
|
||||
.to.emit(exchange, 'Sync')
|
||||
.withArgs(token0Amount, token1Amount)
|
||||
.to.emit(exchange, 'Mint')
|
||||
.withArgs(wallet.address, token0Amount, token1Amount)
|
||||
|
||||
expect(await exchange.totalSupply()).to.eq(expectedLiquidity)
|
||||
expect(await exchange.balanceOf(wallet.address)).to.eq(expectedLiquidity)
|
||||
expect(await exchange.balanceOf(wallet.address)).to.eq(expectedLiquidity.sub(MINIMUM_LIQUIDITY))
|
||||
expect(await token0.balanceOf(exchange.address)).to.eq(token0Amount)
|
||||
expect(await token1.balanceOf(exchange.address)).to.eq(token1Amount)
|
||||
const reserves = await exchange.getReserves()
|
||||
@ -63,8 +68,6 @@ describe('UniswapV2Exchange', () => {
|
||||
await token1.transfer(exchange.address, token1Amount)
|
||||
await exchange.mint(wallet.address, overrides)
|
||||
}
|
||||
|
||||
it('getInputPrice', async () => {
|
||||
const testCases: BigNumber[][] = [
|
||||
[1, 5, 10, '1662497915624478906'],
|
||||
[1, 10, 5, '453305446940074565'],
|
||||
@ -76,18 +79,15 @@ describe('UniswapV2Exchange', () => {
|
||||
[1, 100, 100, '987158034397061298'],
|
||||
[1, 1000, 1000, '996006981039903216']
|
||||
].map(a => a.map((n, i) => (i === 3 ? bigNumberify(n) : expandTo18Decimals(n as number))))
|
||||
|
||||
for (let testCase of testCases) {
|
||||
testCases.forEach((testCase, i) => {
|
||||
it(`getInputPrice:${i}`, async () => {
|
||||
await addLiquidity(testCase[1], testCase[2])
|
||||
await token0.transfer(exchange.address, testCase[0])
|
||||
await expect(exchange.swap(token0.address, testCase[3].add(1), wallet.address, overrides)).to.be.revertedWith(
|
||||
'UniswapV2: K'
|
||||
)
|
||||
await exchange.swap(token0.address, testCase[3], wallet.address, overrides)
|
||||
const totalSupply = await exchange.totalSupply()
|
||||
await exchange.transfer(exchange.address, totalSupply)
|
||||
await exchange.burn(wallet.address, overrides)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('swap:token0', async () => {
|
||||
@ -167,28 +167,28 @@ describe('UniswapV2Exchange', () => {
|
||||
await addLiquidity(token0Amount, token1Amount)
|
||||
|
||||
const expectedLiquidity = expandTo18Decimals(3)
|
||||
await exchange.transfer(exchange.address, expectedLiquidity)
|
||||
await exchange.transfer(exchange.address, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
|
||||
await expect(exchange.burn(wallet.address, overrides))
|
||||
.to.emit(exchange, 'Transfer')
|
||||
.withArgs(exchange.address, AddressZero, expectedLiquidity)
|
||||
.withArgs(exchange.address, AddressZero, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
|
||||
// commented out because of this bug: https://github.com/EthWorks/Waffle/issues/100
|
||||
// .to.emit(token0, 'Transfer')
|
||||
// .withArgs(exchange.address, wallet.address, token0Amount)
|
||||
// .to.emit(token1, 'Transfer')
|
||||
// .withArgs(exchange.address, wallet.address, token1Amount)
|
||||
.to.emit(exchange, 'Sync')
|
||||
.withArgs(0, 0)
|
||||
.withArgs(1000, 1000)
|
||||
.to.emit(exchange, 'Burn')
|
||||
.withArgs(wallet.address, token0Amount, token1Amount, wallet.address)
|
||||
.withArgs(wallet.address, token0Amount.sub(1000), token1Amount.sub(1000), wallet.address)
|
||||
|
||||
expect(await exchange.balanceOf(wallet.address)).to.eq(0)
|
||||
expect(await exchange.totalSupply()).to.eq(0)
|
||||
expect(await token0.balanceOf(exchange.address)).to.eq(0)
|
||||
expect(await token1.balanceOf(exchange.address)).to.eq(0)
|
||||
expect(await exchange.totalSupply()).to.eq(MINIMUM_LIQUIDITY)
|
||||
expect(await token0.balanceOf(exchange.address)).to.eq(1000)
|
||||
expect(await token1.balanceOf(exchange.address)).to.eq(1000)
|
||||
const totalSupplyToken0 = await token0.totalSupply()
|
||||
const totalSupplyToken1 = await token1.totalSupply()
|
||||
expect(await token0.balanceOf(wallet.address)).to.eq(totalSupplyToken0)
|
||||
expect(await token1.balanceOf(wallet.address)).to.eq(totalSupplyToken1)
|
||||
expect(await token0.balanceOf(wallet.address)).to.eq(totalSupplyToken0.sub(1000))
|
||||
expect(await token1.balanceOf(wallet.address)).to.eq(totalSupplyToken1.sub(1000))
|
||||
})
|
||||
|
||||
it('price{0,1}CumulativeLast', async () => {
|
||||
@ -235,9 +235,9 @@ describe('UniswapV2Exchange', () => {
|
||||
await exchange.swap(token1.address, expectedOutputAmount, wallet.address, overrides)
|
||||
|
||||
const expectedLiquidity = expandTo18Decimals(1000)
|
||||
await exchange.transfer(exchange.address, expectedLiquidity)
|
||||
await exchange.transfer(exchange.address, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
|
||||
await exchange.burn(wallet.address, overrides)
|
||||
expect(await exchange.totalSupply()).to.eq(0)
|
||||
expect(await exchange.totalSupply()).to.eq(MINIMUM_LIQUIDITY)
|
||||
})
|
||||
|
||||
it('feeTo:on', async () => {
|
||||
@ -253,12 +253,14 @@ describe('UniswapV2Exchange', () => {
|
||||
await exchange.swap(token1.address, expectedOutputAmount, wallet.address, overrides)
|
||||
|
||||
const expectedLiquidity = expandTo18Decimals(1000)
|
||||
await exchange.transfer(exchange.address, expectedLiquidity)
|
||||
await exchange.transfer(exchange.address, expectedLiquidity.sub(MINIMUM_LIQUIDITY))
|
||||
await exchange.burn(wallet.address, overrides)
|
||||
expect(await exchange.totalSupply()).to.eq('249750499251388')
|
||||
expect(await exchange.totalSupply()).to.eq(MINIMUM_LIQUIDITY.add('249750499251388'))
|
||||
expect(await exchange.balanceOf(other.address)).to.eq('249750499251388')
|
||||
|
||||
expect(await token0.balanceOf(exchange.address)).to.eq('249501683697446')
|
||||
expect(await token1.balanceOf(exchange.address)).to.eq('250000187312968')
|
||||
// using 1000 here instead of the symbolic MINIMUM_LIQUIDITY because the amounts only happen to be equal...
|
||||
// ...because the initial liquidity amounts were equal
|
||||
expect(await token0.balanceOf(exchange.address)).to.eq(bigNumberify(1000).add('249501683697445'))
|
||||
expect(await token1.balanceOf(exchange.address)).to.eq(bigNumberify(1000).add('250000187312969'))
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user