bump solc to 0.5.14
chainId implementation (commented out for now) improve events move safeTransfer in UniswapV2 tweak error messages
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
import "../interfaces/IERC20.sol";
|
||||
import "../libraries/SafeMath.sol";
|
||||
import "./interfaces/IERC20.sol";
|
||||
import "./libraries/SafeMath.sol";
|
||||
|
||||
contract ERC20 is IERC20 {
|
||||
using SafeMath for uint;
|
||||
@ -15,16 +15,12 @@ contract ERC20 is IERC20 {
|
||||
|
||||
bytes32 public DOMAIN_SEPARATOR;
|
||||
// keccak256("Approve(address owner,address spender,uint256 value,uint256 nonce,uint256 expiration)");
|
||||
bytes32 public constant APPROVE_TYPEHASH = hex"25a0822e8c2ed7ff64a57c55df37ff176282195b9e0c9bb770ed24a300c89762";
|
||||
bytes32 public constant APPROVE_TYPEHASH = 0x25a0822e8c2ed7ff64a57c55df37ff176282195b9e0c9bb770ed24a300c89762;
|
||||
mapping (address => uint) public nonces;
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint value);
|
||||
event Approval(address indexed owner, address indexed spender, uint value);
|
||||
|
||||
function MOCK_getChainId() private pure returns (uint) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
constructor(string memory _name, string memory _symbol, uint8 _decimals, uint _totalSupply) public {
|
||||
name = _name;
|
||||
symbol = _symbol;
|
||||
@ -32,11 +28,13 @@ contract ERC20 is IERC20 {
|
||||
if (_totalSupply > 0) {
|
||||
_mint(msg.sender, _totalSupply);
|
||||
}
|
||||
uint chainId = 1; // hardcode as 1 until ethereum-waffle support istanbul-specific EVM opcodes
|
||||
// assembly { chainId := chainid() } // solium-disable-line security/no-inline-assembly
|
||||
DOMAIN_SEPARATOR = keccak256(abi.encode(
|
||||
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
|
||||
keccak256(bytes(name)),
|
||||
keccak256(bytes("1")),
|
||||
MOCK_getChainId(),
|
||||
chainId,
|
||||
address(this)
|
||||
));
|
||||
}
|
||||
@ -47,18 +45,18 @@ contract ERC20 is IERC20 {
|
||||
emit Transfer(address(0), to, value);
|
||||
}
|
||||
|
||||
function _burn(address from, uint value) internal {
|
||||
balanceOf[from] = balanceOf[from].sub(value);
|
||||
totalSupply = totalSupply.sub(value);
|
||||
emit Transfer(from, address(0), value);
|
||||
}
|
||||
|
||||
function _transfer(address from, address to, uint value) private {
|
||||
balanceOf[from] = balanceOf[from].sub(value);
|
||||
balanceOf[to] = balanceOf[to].add(value);
|
||||
emit Transfer(from, to, value);
|
||||
}
|
||||
|
||||
function _burn(address from, uint value) internal {
|
||||
balanceOf[from] = balanceOf[from].sub(value);
|
||||
totalSupply = totalSupply.sub(value);
|
||||
emit Transfer(from, address(0), value);
|
||||
}
|
||||
|
||||
function _approve(address owner, address spender, uint value) private {
|
||||
allowance[owner][spender] = value;
|
||||
emit Approval(owner, spender, value);
|
||||
@ -78,28 +76,6 @@ contract ERC20 is IERC20 {
|
||||
return true;
|
||||
}
|
||||
|
||||
function approveMeta(
|
||||
address owner, address spender, uint value, uint nonce, uint expiration, uint8 v, bytes32 r, bytes32 s
|
||||
)
|
||||
external
|
||||
{
|
||||
require(nonce == nonces[owner]++, "ERC20: INVALID_NONCE");
|
||||
// solium-disable-next-line security/no-block-members
|
||||
require(expiration > block.timestamp, "ERC20: EXPIRED");
|
||||
require(v == 27 || v == 28, "ERC20: INVALID_V");
|
||||
require(uint(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ERC20: INVALID_S");
|
||||
bytes32 digest = keccak256(abi.encodePacked(
|
||||
hex"19",
|
||||
hex"01",
|
||||
DOMAIN_SEPARATOR,
|
||||
keccak256(abi.encode(APPROVE_TYPEHASH, owner, spender, value, nonce, expiration))
|
||||
));
|
||||
address recoveredAddress = ecrecover(digest, v, r, s);
|
||||
require(recoveredAddress != address(0), "ERC20: INVALID_SIGNATURE");
|
||||
require(recoveredAddress == owner, "ERC20: INVALID_ADDRESS");
|
||||
_approve(owner, spender, value);
|
||||
}
|
||||
|
||||
function transferFrom(address from, address to, uint value) external returns (bool) {
|
||||
if (allowance[from][msg.sender] != uint(-1)) {
|
||||
allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
|
||||
@ -114,4 +90,23 @@ contract ERC20 is IERC20 {
|
||||
}
|
||||
_burn(from, value);
|
||||
}
|
||||
|
||||
function approveMeta(
|
||||
address owner, address spender, uint value, uint nonce, uint expiration, uint8 v, bytes32 r, bytes32 s
|
||||
)
|
||||
external
|
||||
{
|
||||
require(nonce == nonces[owner]++, "ERC20: INVALID_NONCE");
|
||||
require(expiration > block.timestamp, "ERC20: EXPIRED"); // solium-disable-line security/no-block-members
|
||||
require(v == 27 || v == 28, "ERC20: INVALID_V");
|
||||
require(uint(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ERC20: INVALID_S");
|
||||
bytes32 digest = keccak256(abi.encodePacked(
|
||||
"\x19\x01",
|
||||
DOMAIN_SEPARATOR,
|
||||
keccak256(abi.encode(APPROVE_TYPEHASH, owner, spender, value, nonce, expiration))
|
||||
));
|
||||
address recoveredAddress = ecrecover(digest, v, r, s);
|
||||
require(recoveredAddress != address(0) && recoveredAddress == owner, "ERC20: INVALID_SIGNATURE");
|
||||
_approve(owner, spender, value);
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,11 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
import "./interfaces/IUniswapV2.sol";
|
||||
import "./libraries/Math.sol";
|
||||
import "./ERC20.sol";
|
||||
import "./libraries/UQ112x112.sol";
|
||||
import "./token/ERC20.sol";
|
||||
import "./token/SafeTransfer.sol";
|
||||
import "./libraries/Math.sol";
|
||||
|
||||
contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTransfer {
|
||||
contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0) {
|
||||
using SafeMath for uint;
|
||||
using UQ112x112 for uint224;
|
||||
|
||||
@ -17,12 +16,17 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran
|
||||
uint112 public reserve0;
|
||||
uint112 public reserve1;
|
||||
uint32 public blockNumberLast;
|
||||
uint public priceCumulative0Last;
|
||||
uint public priceCumulative1Last;
|
||||
uint public price0CumulativeLast;
|
||||
uint public price1CumulativeLast;
|
||||
|
||||
uint private invariantLast;
|
||||
|
||||
bool private notEntered = true;
|
||||
|
||||
event ReservesUpdated(uint112 reserve0, uint112 reserve1);
|
||||
event LiquidityMinted(address indexed sender, uint amount0, uint amount1);
|
||||
event LiquidityBurned(address indexed sender, address indexed recipient, uint amount0, uint amount1);
|
||||
event Swap(address indexed sender, address indexed recipient, address indexed input, uint amount0, uint amount1);
|
||||
|
||||
modifier lock() {
|
||||
require(notEntered, "UniswapV2: LOCKED");
|
||||
notEntered = false;
|
||||
@ -30,65 +34,47 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran
|
||||
notEntered = true;
|
||||
}
|
||||
|
||||
event LiquidityMinted(
|
||||
address indexed sender,
|
||||
address indexed recipient,
|
||||
uint amount0,
|
||||
uint amount1,
|
||||
uint128 reserve0,
|
||||
uint128 reserve1,
|
||||
uint liquidity
|
||||
);
|
||||
event LiquidityBurned(
|
||||
address indexed sender,
|
||||
address indexed recipient,
|
||||
uint amount0,
|
||||
uint amount1,
|
||||
uint128 reserve0,
|
||||
uint128 reserve1,
|
||||
uint liquidity
|
||||
);
|
||||
event Swap(
|
||||
address indexed sender,
|
||||
address indexed recipient,
|
||||
uint amount0,
|
||||
uint amount1,
|
||||
uint128 reserve0,
|
||||
uint128 reserve1,
|
||||
address input
|
||||
);
|
||||
event FeeLiquidityMinted(uint liquidity);
|
||||
|
||||
constructor() public {
|
||||
factory = msg.sender;
|
||||
blockNumberLast = uint32(block.number % 2**32);
|
||||
}
|
||||
|
||||
function initialize(address _token0, address _token1) external {
|
||||
require(msg.sender == factory && token0 == address(0) && token1 == address(0), 'UniswapV2: FORBIDDEN');
|
||||
require(msg.sender == factory && token0 == address(0) && token1 == address(0), "UniswapV2: FORBIDDEN");
|
||||
token0 = _token0;
|
||||
token1 = _token1;
|
||||
}
|
||||
|
||||
function safeTransfer(address token, address to, uint value) private {
|
||||
// solium-disable-next-line security/no-low-level-calls
|
||||
(bool success, bytes memory data) = token.call(abi.encodeWithSignature("transfer(address,uint256)", to, value));
|
||||
require(success, "UniswapV2: TRANSFER_UNSUCCESSFUL");
|
||||
if (data.length > 0) {
|
||||
require(abi.decode(data, (bool)), "SafeTransfer: TRANSFER_FAILED");
|
||||
}
|
||||
}
|
||||
|
||||
function getInputPrice(uint inputAmount, uint inputReserve, uint outputReserve) public pure returns (uint) {
|
||||
require(inputReserve > 0 && outputReserve > 0, "UniswapV2: INVALID_VALUE");
|
||||
require(inputReserve > 0 && outputReserve > 0, "UniswapV2: INSUFFICIENT_RESERVES");
|
||||
uint amountInputWithFee = inputAmount.mul(997);
|
||||
uint numerator = amountInputWithFee.mul(outputReserve);
|
||||
uint denominator = inputReserve.mul(1000).add(amountInputWithFee);
|
||||
return numerator / denominator;
|
||||
}
|
||||
|
||||
// increment price accumulators if necessary, and update reserves
|
||||
function update(uint balance0, uint balance1) private {
|
||||
uint32 blockNumber = uint32(block.number % 2**32);
|
||||
uint32 blocksElapsed = blockNumber - blockNumberLast; // overflow is desired
|
||||
if (blocksElapsed > 0 && reserve0 != 0 && reserve1 != 0) {
|
||||
// in the following 2 lines, * never overflows, + overflow is desired
|
||||
priceCumulative0Last += uint256(UQ112x112.encode(reserve0).qdiv(reserve1)) * blocksElapsed;
|
||||
priceCumulative1Last += uint256(UQ112x112.encode(reserve1).qdiv(reserve0)) * blocksElapsed;
|
||||
// * never overflows, and + overflow is desired
|
||||
price0CumulativeLast += uint256(UQ112x112.encode(reserve0).qdiv(reserve1)) * blocksElapsed;
|
||||
price1CumulativeLast += uint256(UQ112x112.encode(reserve1).qdiv(reserve0)) * blocksElapsed;
|
||||
}
|
||||
reserve0 = balance0.clamp112();
|
||||
reserve1 = balance1.clamp112();
|
||||
reserve0 = Math.clamp112(balance0);
|
||||
reserve1 = Math.clamp112(balance1);
|
||||
blockNumberLast = blockNumber;
|
||||
emit ReservesUpdated(reserve0, reserve1);
|
||||
}
|
||||
|
||||
// mint liquidity equivalent to 20% of accumulated fees
|
||||
@ -98,15 +84,16 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran
|
||||
uint numerator = totalSupply.mul(invariant.sub(invariantLast));
|
||||
uint denominator = uint256(4).mul(invariant).add(invariantLast);
|
||||
uint liquidity = numerator / denominator;
|
||||
_mint(factory, liquidity); // factory is just a placeholder
|
||||
emit FeeLiquidityMinted(liquidity);
|
||||
if (liquidity > 0) {
|
||||
_mint(factory, liquidity); // factory is a placeholder
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mintLiquidity(address recipient) external lock returns (uint liquidity) {
|
||||
uint balance0 = IERC20(token0).balanceOf(address(this));
|
||||
uint balance1 = IERC20(token1).balanceOf(address(this));
|
||||
require(balance0 <= uint112(-1) && balance1 <= uint112(-1), "UniswapV2: EXCESS_LIQUIDITY");
|
||||
require(balance0 <= uint112(-1) && balance1 <= uint112(-1), "UniswapV2: EXCESS_BALANCES");
|
||||
uint amount0 = balance0.sub(reserve0);
|
||||
uint amount1 = balance1.sub(reserve1);
|
||||
|
||||
@ -114,31 +101,31 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran
|
||||
liquidity = totalSupply == 0 ?
|
||||
Math.sqrt(amount0.mul(amount1)) :
|
||||
Math.min(amount0.mul(totalSupply) / reserve0, amount1.mul(totalSupply) / reserve1);
|
||||
require(liquidity > 0, "UniswapV2: INSUFFICIENT_VALUE");
|
||||
require(liquidity > 0, "UniswapV2: INSUFFICIENT_LIQUIDITY");
|
||||
_mint(recipient, liquidity);
|
||||
|
||||
update(balance0, balance1);
|
||||
invariantLast = Math.sqrt(uint(reserve0).mul(reserve1));
|
||||
emit LiquidityMinted(msg.sender, recipient, amount0, amount1, reserve0, reserve1, liquidity);
|
||||
emit LiquidityMinted(msg.sender, amount0, amount1);
|
||||
}
|
||||
|
||||
function burnLiquidity(address recipient) external lock returns (uint amount0, uint amount1) {
|
||||
uint liquidity = balanceOf[address(this)];
|
||||
uint balance0 = IERC20(token0).balanceOf(address(this));
|
||||
uint balance1 = IERC20(token1).balanceOf(address(this));
|
||||
require(balance0 >= reserve0 && balance0 >= reserve1, "UniswapV2: INSUFFICIENT_BALANCE");
|
||||
require(balance0 >= reserve0 && balance0 >= reserve1, "UniswapV2: INSUFFICIENT_BALANCES");
|
||||
|
||||
mintFeeLiquidity();
|
||||
amount0 = liquidity.mul(balance0) / totalSupply; // intentionally using balances not reserves
|
||||
amount1 = liquidity.mul(balance1) / totalSupply; // intentionally using balances not reserves
|
||||
require(amount0 > 0 && amount1 > 0, "UniswapV2: INSUFFICIENT_VALUE");
|
||||
require(amount0 > 0 && amount1 > 0, "UniswapV2: INSUFFICIENT_AMOUNTS");
|
||||
safeTransfer(token0, recipient, amount0);
|
||||
safeTransfer(token1, recipient, amount1);
|
||||
_burn(address(this), liquidity);
|
||||
|
||||
update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)));
|
||||
invariantLast = Math.sqrt(uint(reserve0).mul(reserve1));
|
||||
emit LiquidityBurned(msg.sender, recipient, amount0, amount1, reserve0, reserve1, liquidity);
|
||||
emit LiquidityBurned(msg.sender, recipient, amount0, amount1);
|
||||
}
|
||||
|
||||
function swap0(address recipient) external lock returns (uint amount1) {
|
||||
@ -147,11 +134,11 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran
|
||||
uint amount0 = balance0.sub(reserve0);
|
||||
|
||||
amount1 = getInputPrice(amount0, reserve0, reserve1);
|
||||
require(amount1 > 0, "UniswapV2: INSUFFICIENT_VALUE");
|
||||
require(amount1 > 0, "UniswapV2: INSUFFICIENT_AMOUNT");
|
||||
safeTransfer(token1, recipient, amount1);
|
||||
|
||||
update(balance0, IERC20(token1).balanceOf(address(this)));
|
||||
emit Swap(msg.sender, recipient, amount0, amount1, reserve0, reserve1, token0);
|
||||
emit Swap(msg.sender, recipient, token0, amount0, amount1);
|
||||
}
|
||||
|
||||
function swap1(address recipient) external lock returns (uint amount0) {
|
||||
@ -160,14 +147,14 @@ contract UniswapV2 is IUniswapV2, ERC20("Uniswap V2", "UNI-V2", 18, 0), SafeTran
|
||||
uint amount1 = balance1.sub(reserve1);
|
||||
|
||||
amount0 = getInputPrice(amount1, reserve1, reserve0);
|
||||
require(amount0 > 0, "UniswapV2: INSUFFICIENT_VALUE");
|
||||
require(amount0 > 0, "UniswapV2: INSUFFICIENT_AMOUNT");
|
||||
safeTransfer(token0, recipient, amount0);
|
||||
|
||||
update(IERC20(token0).balanceOf(address(this)), balance1);
|
||||
emit Swap(msg.sender, recipient, amount0, amount1, reserve0, reserve1, token1);
|
||||
emit Swap(msg.sender, recipient, token1, amount0, amount1);
|
||||
}
|
||||
|
||||
// almost never _needs_ to be called, it's for weird tokens and can also be helpful for oracles
|
||||
// almost certainly never needs to be called, but can be helpful for oracles and possibly some weird tokens
|
||||
function sync() external lock {
|
||||
update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)));
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
import "./interfaces/IUniswapV2Factory.sol";
|
||||
import "./UniswapV2.sol";
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
interface IERC20 {
|
||||
event Transfer(address indexed from, address indexed to, uint value);
|
||||
@ -20,7 +20,6 @@ interface IERC20 {
|
||||
function approve(address spender, uint value) external returns (bool);
|
||||
function transferFrom(address from, address to, uint value) external returns (bool);
|
||||
function burnFrom(address from, uint value) external;
|
||||
|
||||
function approveMeta(
|
||||
address owner, address spender, uint value, uint nonce, uint expiration, uint8 v, bytes32 r, bytes32 s
|
||||
)
|
||||
|
||||
@ -1,34 +1,10 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
interface IUniswapV2 {
|
||||
event LiquidityMinted(
|
||||
address indexed sender,
|
||||
address indexed recipient,
|
||||
uint amount0,
|
||||
uint amount1,
|
||||
uint128 reserve0,
|
||||
uint128 reserve1,
|
||||
uint liquidity
|
||||
);
|
||||
event LiquidityBurned(
|
||||
address indexed sender,
|
||||
address indexed recipient,
|
||||
uint amount0,
|
||||
uint amount1,
|
||||
uint128 reserve0,
|
||||
uint128 reserve1,
|
||||
uint liquidity
|
||||
);
|
||||
event Swap(
|
||||
address indexed sender,
|
||||
address indexed recipient,
|
||||
uint amount0,
|
||||
uint amount1,
|
||||
uint128 reserve0,
|
||||
uint128 reserve1,
|
||||
address input
|
||||
);
|
||||
event FeeLiquidityMinted(uint liquidity);
|
||||
event ReservesUpdated(uint112 reserve0, uint112 reserve1);
|
||||
event LiquidityMinted(address indexed sender, uint amount0, uint amount1);
|
||||
event LiquidityBurned(address indexed sender, address indexed recipient, uint amount0, uint amount1);
|
||||
event Swap(address indexed sender, address indexed recipient, address indexed input, uint amount0, uint amount1);
|
||||
|
||||
function factory() external view returns (address);
|
||||
function token0() external view returns (address);
|
||||
@ -37,8 +13,8 @@ interface IUniswapV2 {
|
||||
function reserve0() external view returns (uint112);
|
||||
function reserve1() external view returns (uint112);
|
||||
function blockNumberLast() external view returns (uint32);
|
||||
function priceCumulative0Last() external view returns (uint);
|
||||
function priceCumulative1Last() external view returns (uint);
|
||||
function price0CumulativeLast() external view returns (uint);
|
||||
function price1CumulativeLast() external view returns (uint);
|
||||
|
||||
function getInputPrice(uint inputAmount, uint inputReserve, uint outputReserve) external pure returns (uint);
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
interface IUniswapV2Factory {
|
||||
event ExchangeCreated(address indexed token0, address indexed token1, address exchange, uint256 exchangeNumber);
|
||||
|
||||
@ -1,18 +1,24 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
library Math {
|
||||
function min(uint x, uint y) internal pure returns (uint z) {
|
||||
return x <= y ? x : y;
|
||||
z = x <= y ? x : y;
|
||||
}
|
||||
|
||||
function clamp112(uint y) internal pure returns (uint112 z) {
|
||||
z = y <= uint112(-1) ? uint112(y) : uint112(-1);
|
||||
}
|
||||
|
||||
function sqrt(uint y) internal pure returns (uint z) {
|
||||
if (y == 0) return 0;
|
||||
else if (y <= 3) return 1;
|
||||
if (y > 3) {
|
||||
uint x = (y + 1) / 2;
|
||||
z = y;
|
||||
while (x < z) {
|
||||
z = x;
|
||||
x = (y / x + x) / 2;
|
||||
}
|
||||
} else if (y != 0) {
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,17 +1,15 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
library SafeMath {
|
||||
function add(uint x, uint y) internal pure returns (uint z) {
|
||||
require((z = x + y) >= x, "ds-math-add-overflow");
|
||||
}
|
||||
|
||||
function sub(uint x, uint y) internal pure returns (uint z) {
|
||||
require((z = x - y) <= x, "ds-math-sub-underflow");
|
||||
}
|
||||
|
||||
function mul(uint x, uint y) internal pure returns (uint z) {
|
||||
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
|
||||
}
|
||||
|
||||
function clamp112(uint y) internal pure returns (uint112 z) {
|
||||
z = y <= uint112(-1) ? uint112(y) : uint112(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
pragma solidity 0.5.13;
|
||||
pragma solidity 0.5.14;
|
||||
|
||||
library UQ112x112 {
|
||||
uint224 constant Q112 = 2**112;
|
||||
|
||||
// encode a uint112 as a UQ112.112 fixed point number s.t. `y := y_encoded / 2**112` (i.e. with a Q112 denominator).
|
||||
// encode a uint112 as a UQ112.112 fixed point number s.t. `y := z / 2**112`
|
||||
function encode(uint112 y) internal pure returns (uint224 z) {
|
||||
z = uint224(y) * Q112; // never overflows
|
||||
}
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
pragma solidity 0.5.13;
|
||||
|
||||
contract SafeTransfer {
|
||||
function safeTransfer(address token, address to, uint value) internal {
|
||||
// solium-disable-next-line security/no-low-level-calls
|
||||
(bool success, bytes memory data) = token.call(abi.encodeWithSignature("transfer(address,uint256)", to, value));
|
||||
require(success, "SafeTransfer: SWAP_FAILED");
|
||||
if (data.length > 0) {
|
||||
require(abi.decode(data, (bool)), "SafeTransfer: SWAP_UNSUCCESSFUL");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
"node": "^10"
|
||||
},
|
||||
"dependencies": {
|
||||
"solc": "0.5.13"
|
||||
"solc": "0.5.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chai": "^4.2.6",
|
||||
|
||||
@ -6,6 +6,7 @@ import { BigNumber, bigNumberify } from 'ethers/utils'
|
||||
|
||||
import { expandTo18Decimals } from './shared/utilities'
|
||||
import { exchangeFixture, ExchangeFixture } from './shared/fixtures'
|
||||
import { AddressZero } from 'ethers/constants'
|
||||
|
||||
chai.use(solidity)
|
||||
const { expect } = chai
|
||||
@ -69,15 +70,9 @@ describe('UniswapV2', () => {
|
||||
await token1.transfer(exchange.address, token1Amount)
|
||||
await expect(exchange.connect(wallet).mintLiquidity(wallet.address))
|
||||
.to.emit(exchange, 'LiquidityMinted')
|
||||
.withArgs(
|
||||
wallet.address,
|
||||
wallet.address,
|
||||
token0Amount,
|
||||
token1Amount,
|
||||
token0Amount,
|
||||
token1Amount,
|
||||
expectedLiquidity
|
||||
)
|
||||
.withArgs(wallet.address, token0Amount, token1Amount)
|
||||
.to.emit(exchange, 'Transfer')
|
||||
.withArgs(AddressZero, wallet.address, expectedLiquidity)
|
||||
|
||||
expect(await exchange.totalSupply()).to.eq(expectedLiquidity)
|
||||
expect(await exchange.balanceOf(wallet.address)).to.eq(expectedLiquidity)
|
||||
@ -92,18 +87,19 @@ describe('UniswapV2', () => {
|
||||
await exchange.connect(wallet).mintLiquidity(wallet.address)
|
||||
}
|
||||
|
||||
// it('swap:gas', async () => {
|
||||
// const token0Amount = expandTo18Decimals(5)
|
||||
// const token1Amount = expandTo18Decimals(10)
|
||||
// await addLiquidity(token0Amount, token1Amount)
|
||||
it('swap:gas', async () => {
|
||||
const token0Amount = expandTo18Decimals(5)
|
||||
const token1Amount = expandTo18Decimals(10)
|
||||
await addLiquidity(token0Amount, token1Amount)
|
||||
|
||||
// const swapAmount = expandTo18Decimals(1)
|
||||
// await token0.transfer(exchange.address, swapAmount)
|
||||
// await exchange.connect(wallet).swap0(wallet.address)
|
||||
const swapAmount = expandTo18Decimals(1)
|
||||
await token0.transfer(exchange.address, swapAmount)
|
||||
await exchange.connect(wallet).swap0(wallet.address)
|
||||
|
||||
// await token0.transfer(exchange.address, swapAmount)
|
||||
// console.log((await exchange.estimate.swap0(wallet.address)).toString())
|
||||
// })
|
||||
await token0.transfer(exchange.address, swapAmount)
|
||||
const gasCost = await exchange.estimate.swap0(wallet.address)
|
||||
console.log(`Gas cost of swap: ${gasCost}`)
|
||||
})
|
||||
|
||||
it('swap', async () => {
|
||||
const token0Amount = expandTo18Decimals(5)
|
||||
@ -115,15 +111,9 @@ describe('UniswapV2', () => {
|
||||
await token0.transfer(exchange.address, swapAmount)
|
||||
await expect(exchange.connect(wallet).swap0(wallet.address))
|
||||
.to.emit(exchange, 'Swap')
|
||||
.withArgs(
|
||||
wallet.address,
|
||||
wallet.address,
|
||||
swapAmount,
|
||||
expectedOutputAmount,
|
||||
token0Amount.add(swapAmount),
|
||||
token1Amount.sub(expectedOutputAmount),
|
||||
token0.address
|
||||
)
|
||||
.withArgs(wallet.address, wallet.address, token0.address, swapAmount, expectedOutputAmount)
|
||||
.to.emit(exchange, 'ReservesUpdated')
|
||||
.withArgs(token0Amount.add(swapAmount), token1Amount.sub(expectedOutputAmount))
|
||||
|
||||
expect(await token0.balanceOf(exchange.address)).to.eq(token0Amount.add(swapAmount))
|
||||
expect(await token1.balanceOf(exchange.address)).to.eq(token1Amount.sub(expectedOutputAmount))
|
||||
@ -143,7 +133,9 @@ describe('UniswapV2', () => {
|
||||
await exchange.connect(wallet).transfer(exchange.address, liquidity)
|
||||
await expect(exchange.connect(wallet).burnLiquidity(wallet.address))
|
||||
.to.emit(exchange, 'LiquidityBurned')
|
||||
.withArgs(wallet.address, wallet.address, token0Amount, token1Amount, bigNumberify(0), bigNumberify(0), liquidity)
|
||||
.withArgs(wallet.address, wallet.address, token0Amount, token1Amount)
|
||||
.to.emit(exchange, 'ReservesUpdated')
|
||||
.withArgs(bigNumberify(0), bigNumberify(0))
|
||||
|
||||
expect(await exchange.balanceOf(wallet.address)).to.eq(0)
|
||||
expect(await token0.balanceOf(exchange.address)).to.eq(0)
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"evmVersion": "istanbul",
|
||||
"optimizer": {
|
||||
"enabled": true,
|
||||
"runs": 1000
|
||||
"runs": 200
|
||||
}
|
||||
},
|
||||
"ganacheOptions": {
|
||||
|
||||
16
yarn.lock
16
yarn.lock
@ -6019,7 +6019,21 @@ snapdragon@^0.8.1:
|
||||
source-map-resolve "^0.5.0"
|
||||
use "^3.1.0"
|
||||
|
||||
solc@0.5.13, solc@^0.5.10:
|
||||
solc@0.5.14:
|
||||
version "0.5.14"
|
||||
resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.14.tgz#7c3ecb2441ac10a15cdfd39207372eb63f2bd00c"
|
||||
integrity sha512-I/MCeOKjnLXxcD65wA+E37BxdERoAYoLeyJ5GnXFijICLmvhzt0xz59R92Zw3TPyJYnHSErKBYpMsfnZVyQJaQ==
|
||||
dependencies:
|
||||
command-exists "^1.2.8"
|
||||
commander "3.0.2"
|
||||
fs-extra "^0.30.0"
|
||||
js-sha3 "0.8.0"
|
||||
memorystream "^0.3.1"
|
||||
require-from-string "^2.0.0"
|
||||
semver "^5.5.0"
|
||||
tmp "0.0.33"
|
||||
|
||||
solc@^0.5.10:
|
||||
version "0.5.13"
|
||||
resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.13.tgz#2a5ba2b7681898c6293759441e0a768fb6955def"
|
||||
integrity sha512-osybDVPGjAqcmSKLU3vh5iHuxbhGlJjQI5ZvI7nRDR0fgblQqYte4MGvNjbew8DPvCrmoH0ZBiz/KBBLlPxfMg==
|
||||
|
||||
Reference in New Issue
Block a user