diff --git a/contracts/UniswapV2Factory.sol b/contracts/UniswapV2Factory.sol index f06ec1a..0ecf4c1 100644 --- a/contracts/UniswapV2Factory.sol +++ b/contracts/UniswapV2Factory.sol @@ -1,73 +1,54 @@ pragma solidity 0.5.12; import "./interfaces/IUniswapV2Factory.sol"; - import "./UniswapV2.sol"; contract UniswapV2Factory is IUniswapV2Factory { bytes public exchangeBytecode; - mapping (address => address[2]) private exchangeToTokens; - mapping (address => mapping(address => address)) private token0ToToken1ToExchange; - mapping (address => address[]) private tokensToOtherTokens; - address[] public exchanges; + mapping (address => mapping(address => address)) private _getExchange; + mapping (address => address[2]) private _getTokens; + address[] public getExchanges; event ExchangeCreated(address indexed token0, address indexed token1, address exchange, uint exchangeNumber); constructor(bytes memory _exchangeBytecode) public { - require(_exchangeBytecode.length >= 0x20, "UniswapV2Factory: SHORT_BYTECODE"); + require(_exchangeBytecode.length >= 32, "UniswapV2Factory: SHORT_BYTECODE"); exchangeBytecode = _exchangeBytecode; } - function getTokens(address exchange) external view returns (address token0, address token1) { - return (exchangeToTokens[exchange][0], exchangeToTokens[exchange][1]); - } - - function getExchange(address tokenA, address tokenB) external view returns (address exchange) { - (address token0, address token1) = getTokenOrder(tokenA, tokenB); - return token0ToToken1ToExchange[token0][token1]; - } - - function getOtherTokens(address token) external view returns (address[] memory) { - return tokensToOtherTokens[token]; - } - - function getOtherTokensLength(address token) external view returns (uint) { - return tokensToOtherTokens[token].length; - } - - function getExchangesLength() external view returns(uint) { - return exchanges.length; - } - - function getTokenOrder(address tokenA, address tokenB) private pure returns (address token0, address token1) { + function sortTokens(address tokenA, address tokenB) public pure returns (address, address) { return tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); } + function getExchange(address tokenA, address tokenB) external view returns (address) { + (address token0, address token1) = sortTokens(tokenA, tokenB); + return _getExchange[token0][token1]; + } + + function getTokens(address exchange) external view returns (address, address) { + return (_getTokens[exchange][0], _getTokens[exchange][1]); + } + + function getExchangesCount() external view returns (uint) { + return getExchanges.length; + } + function createExchange(address tokenA, address tokenB) external returns (address exchange) { require(tokenA != tokenB, "UniswapV2Factory: SAME_ADDRESS"); require(tokenA != address(0) && tokenB != address(0), "UniswapV2Factory: ZERO_ADDRESS"); - - (address token0, address token1) = getTokenOrder(tokenA, tokenB); - require(token0ToToken1ToExchange[token0][token0] == address(0), "UniswapV2Factory: EXCHANGE_EXISTS"); + (address token0, address token1) = sortTokens(tokenA, tokenB); + require(_getExchange[token0][token1] == address(0), "UniswapV2Factory: EXCHANGE_EXISTS"); bytes memory exchangeBytecodeMemory = exchangeBytecode; bytes32 salt = keccak256(abi.encodePacked(token0, token1)); - assembly { - exchange := create2( - 0, - add(exchangeBytecodeMemory, 0x20), - mload(exchangeBytecodeMemory), - salt - ) + assembly { // solium-disable-line security/no-inline-assembly + exchange := create2(0, add(exchangeBytecodeMemory, 32), mload(exchangeBytecodeMemory), salt) } UniswapV2(exchange).initialize(token0, token1); - exchangeToTokens[exchange] = [token0, token1]; - token0ToToken1ToExchange[token0][token1] = exchange; - tokensToOtherTokens[token0].push(token1); - tokensToOtherTokens[token1].push(token0); - - emit ExchangeCreated(token0, token1, exchange, exchanges.push(exchange)); + _getExchange[token0][token1] = exchange; + _getTokens[exchange] = [token0, token1]; + emit ExchangeCreated(token0, token1, exchange, getExchanges.push(exchange)); } } diff --git a/contracts/interfaces/IERC20.sol b/contracts/interfaces/IERC20.sol index c8fe754..17b2f29 100644 --- a/contracts/interfaces/IERC20.sol +++ b/contracts/interfaces/IERC20.sol @@ -11,6 +11,10 @@ interface IERC20 { function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); + function DOMAIN_SEPARATOR() external view returns (bytes32); + function APPROVE_TYPEHASH() external pure returns (bytes32); + function nonces(address owner) external view returns (uint); + function transfer(address to, uint value) external returns (bool); function approve(address spender, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); @@ -18,9 +22,6 @@ interface IERC20 { function burn(uint value) external; function burnFrom(address from, uint value) external; - function DOMAIN_SEPARATOR() external view returns (bytes32); - function APPROVE_TYPEHASH() external pure returns (bytes32); - function nonces(address owner) external view returns (uint); function approveMeta( address owner, address spender, uint value, uint nonce, uint expiration, uint8 v, bytes32 r, bytes32 s diff --git a/contracts/interfaces/IUniswapV2Factory.sol b/contracts/interfaces/IUniswapV2Factory.sol index ed85de8..c901c36 100644 --- a/contracts/interfaces/IUniswapV2Factory.sol +++ b/contracts/interfaces/IUniswapV2Factory.sol @@ -4,13 +4,12 @@ interface IUniswapV2Factory { event ExchangeCreated(address indexed token0, address indexed token1, address exchange, uint256 exchangeNumber); function exchangeBytecode() external view returns (bytes memory); - function exchanges(uint256) external view returns (address); - function getTokens(address exchange) external view returns (address, address); + function sortTokens(address tokenA, address tokenB) external pure returns (address, address); function getExchange(address tokenA, address tokenB) external view returns (address); - function getOtherTokens(address token) external view returns (address[] memory); - function getOtherTokensLength(address token) external view returns (uint256); + function getTokens(address exchange) external view returns (address, address); + function getExchanges() external view returns (address[] memory); + function getExchangesCount() external view returns (uint); function createExchange(address tokenA, address tokenB) external returns (address exchange); - function getExchangesLength() external view returns(uint256); } diff --git a/contracts/token/ERC20.sol b/contracts/token/ERC20.sol index 4e16a22..10bfd00 100644 --- a/contracts/token/ERC20.sol +++ b/contracts/token/ERC20.sol @@ -7,15 +7,13 @@ import "../libraries/SafeMath.sol"; contract ERC20 is IERC20 { using SafeMath for uint; - // ERC-20 data string public name; string public symbol; uint8 public decimals; - uint public totalSupply; + uint public totalSupply; mapping (address => uint) public balanceOf; mapping (address => mapping (address => uint)) public allowance; - // ERC-721 data bytes32 public DOMAIN_SEPARATOR; // keccak256("Approve(address owner,address spender,uint256 value,uint256 nonce,uint256 expiration)"); bytes32 public constant APPROVE_TYPEHASH = hex'25a0822e8c2ed7ff64a57c55df37ff176282195b9e0c9bb770ed24a300c89762'; @@ -85,6 +83,7 @@ contract ERC20 is IERC20 { external { require(nonce == nonces[owner]++, "ERC20: INVALID_NONCE"); + // solium-disable-next-line security/no-block-members require(expiration > block.timestamp, "ERC20: EXPIRED_SIGNATURE"); require(v == 27 || v == 28, "ECDSA: INVALID_V"); require(uint(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0, "ECDSA: INVALID_S"); diff --git a/contracts/token/SafeTransfer.sol b/contracts/token/SafeTransfer.sol index f29af94..4310b56 100644 --- a/contracts/token/SafeTransfer.sol +++ b/contracts/token/SafeTransfer.sol @@ -2,14 +2,11 @@ pragma solidity 0.5.12; 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_REVERTED"); - - if (data.length == 32) { + require(success, "SafeTransfer: SWAP_FAILED"); + if (data.length > 0) { require(abi.decode(data, (bool)), "SafeTransfer: SWAP_UNSUCCESSFUL"); - } else if (data.length > 32) { - revert("SafeTransfer: SWAP_INVALID_RETURN"); } } } \ No newline at end of file