MINIMUM_TOTAL_SUPPLY -> MINIMUM_LIQUIDITY (#51)

* MINIMUM_TOTAL_SUPPLY -> MINIMUM_LIQUIDITY

make selector private
This commit is contained in:
Noah Zinsmeister
2020-02-07 10:38:46 -05:00
committed by GitHub
parent 188eb5ac6d
commit 55ae25109b
5 changed files with 48 additions and 49 deletions

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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'))
})
})