# Uniswap demo features
See the existing [Solidity contracts](https://github.com/Uniswap/uniswap-v2-core/tree/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts) for reference. In general, I think the Fe implementation will look similar to the Solidity implementation.
## Must have
**1.) multiple contracts in one module**
The parser is able to handle multiple contracts defined within a single module file. In the compiler though, we only take the first contract definition and ignore the rest. We need to change this so that each contract is compiled. Furthermore, we need to store data about each contract in the module scope so that we access contract bytecode and ABIs when compiling the other contracts.
**2.) contract creation**
```
bytes memory bytecode = type(UniswapV2Pair).creationCode;
bytes32 salt = keccak256(abi.encodePacked(token0, token1));
assembly {
pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
}
```
[code](https://github.com/Uniswap/uniswap-v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts/UniswapV2Factory.sol#L28-L32)
In light of feature 1, information about `UniswapV2Pair` will be visible in the module scope. Figuring out how to wire things up exactly is something that can be done when an issue is written. But, what we ultimately want to do is include the contract (`UniswapV2Pair`) in the runtime as a Yul object and then map a statement like `UniswapV2Pair.create2(<value>, <nonce>)` to a Yul statement that copies the contract's data into memory and calls the builtin function `create2` with the size and location of the copied contract.
The expression `UniswapV2Pair.create2(<value>, <nonce>)` would be of type `UniswapV2Pair`. This type would have the contract's public functions attributed to it as callable functions. In the translated Yul code, the expression would evaluate to the contract's new address.
See the Yul docs for an [example](https://docs.soliditylang.org/en/v0.7.0/yul.html#specification-of-yul-object) of nested contract objects.
**3.) loading existing contracts**
```
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
```
[code](https://github.com/Uniswap/uniswap-v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts/UniswapV2Pair.sol#L150-L151)
Similar to feature 2, we need to enable to enable the use of an expression like `ERC20.from(my_address)`. The only difference between this expression and `UniswapV2Pair.create2(<value>, <nonce>)` is that we do not run the `create2` operation. Both expressions evaluate to a contract type with public functions attributed to it.
In the Solidity contracts, they're using an interface object. For now, we can just use a vanilla ERC20 contract instead of an interface.
**4.) string literals**
There are a number of places in the Uniswap contracts where string literals are used. Here are a few examples:
```
// function scope
require(tokenA != tokenB, 'UniswapV2: IDENTICAL_ADDRESSES');
...
// contract scope
string public constant name = 'Uniswap V2';
```
The easiest way to handle string literals would probably be to store them as data objects that are loaded into memory when referenced. See the Yul docs for an [example](https://docs.soliditylang.org/en/v0.7.0/yul.html#specification-of-yul-object) of data objects.
**5.) non-empty tuples consisting of base types**
There are a couple places where tuples consisting of base types are used as return types.
```
function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast)
```
[code](https://github.com/Uniswap/uniswap-v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts/UniswapV2Pair.sol#L38-L42)
*note: I'm not quite sure why `uint112` is used here.*
```
function burn(address to) external lock returns (uint amount0, uint amount1)
```
[code](https://github.com/Uniswap/uniswap-v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts/UniswapV2Pair.sol#L134-L156)
**5.) `keccak256` function**
It should be possible to do things like `my_num.keccak256()` and `my_tuple.keccak256()`.
**6.) `abi_encode_packed` and `abi_encode` functions**
It should be possible to encode values by doing something like `my_array.abi_encode()` and `my_tuple.abi_encode_packed`.
**7.) a few more global values**
- `chain.id`
- `block.timestamp`
**8.) Math.sqrt(n)**
We need to provide access to a square root function.
## Should have
**10.) things used in the ERC20 permit function**
```
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
require(deadline >= block.timestamp, 'UniswapV2: EXPIRED');
bytes32 digest = keccak256(
abi.encodePacked(
'\x19\x01',
DOMAIN_SEPARATOR,
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(recoveredAddress != address(0) && recoveredAddress == owner, 'UniswapV2: INVALID_SIGNATURE');
_approve(owner, spender, value);
}
```
[code](https://github.com/Uniswap/uniswap-v2-core/blob/4dd59067c76dea4a0e8e4bfdda41877a6b16dedc/contracts/UniswapV2ERC20.sol#L81-L93)
This is a bit vague as I don't fully understand what's going on here. At a glance, it looks like we need at least the following:
- Expose ABI encoding functions to the user (mentioned above)
- We may want to enable encoding via attribute functions like `my_tuple.encodePacked()`. If we go this route though, we would need to add support for byte arrays in tuples.
- Expose keccak256 to the user (mentioned above)
- I'd suggest the syntax: `my_bytes.keccak256()`.
- Expose ercrecover to the user
- `crypto.ercrecover`
See the relevant docs:
- https://eips.ethereum.org/EIPS/eip-712
- https://uniswap.org/docs/v2/smart-contracts/pair-erc-20
## Nice to have
**20.) const values**
There are a few places where `const` modifiers are used on contract fields. Here's an example:
```
uint public constant MINIMUM_LIQUIDITY = 10**3;
```
We could do something similar like `const my_val: u256 = 5`, where the value is placed in the bytecode instead of storage. This would save alot of gas.
**21.) `pub` modifier on contract fields**
```
contract UniswapV2Factory:
pub fee_to: address
pub fee_to_setter: address
```
Using `pub` on a contract field should make the value of the field visible outside of the contract.