- 
                Notifications
    You must be signed in to change notification settings 
- Fork 75
feat(contracts): Add LP logic #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: chrismaree <christopher.maree@gmail.com>
| // Next, remove half the liquidity as ETH (set sendETH = true). This should modify the eth bal but not the weth bal. | ||
| await expect(() => | ||
| hubPool.connect(liquidityProvider).removeLiquidity(weth.address, amountToLp.div(2), true) | ||
| ).to.changeEtherBalance(liquidityProvider, amountToLp.div(2)); // There should be ETH transferred, not WETH. | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this syntax is great! unfortunately it cant be chained along with a .to.changeTokenBalance so I did this the old fashion way.
| @@ -0,0 +1,38 @@ | |||
| import { expect } from "chai"; | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
notice that I've separated sets of tests into files. goal is to not have one massive file and rather just run some fixtures and have fewer shorter test files.
|  | ||
| const config: HardhatUserConfig = { | ||
| solidity: "0.8.11", | ||
| solidity: { compilers: [{ version: "0.8.11", settings: { optimizer: { enabled: true, runs: 200 } } }] }, | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Set runs to 1_000_000?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
| import { ethers } from "hardhat"; | ||
| import { Contract, BigNumber } from "ethers"; | ||
|  | ||
| export async function deployHubPoolTestHelperContracts(deployerWallet: any) { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome first PR on the HubPool lgtm!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! A few minor comments and high level questions
        
          
                test/HubPool.TokenWhitelisting.ts
              
                Outdated
          
        
      | import { getContractFactory } from "./utils"; | ||
| import { deployHubPoolTestHelperContracts } from "./HubPool.Fixture"; | ||
|  | ||
| let hubPool: Contract, weth: Contract, owner: any, liquidityProvider: any, other: any; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't signers have a type we can use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could not easily find. will try again
        
          
                test/HubPool.LiquidityProvision.ts
              
                Outdated
          
        
      | let timer: Contract; | ||
| let hubPool: Contract, weth: Contract, usdc: Contract, dai: Contract; | ||
| let wethLpToken: Contract, usdcLpToken: Contract, daiLpToken: Contract; | ||
| let owner: any, liquidityProvider: any, other: any; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. I think there's a simple type we could use for these
| } | ||
|  | ||
| export async function seedWallet( | ||
| walletToFund: any, | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
|  | ||
| const config: HardhatUserConfig = { | ||
| solidity: "0.8.11", | ||
| solidity: { compilers: [{ version: "0.8.11", settings: { optimizer: { enabled: true, runs: 200 } } }] }, | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
| url: process.env.ROPSTEN_URL || "", | ||
| accounts: | ||
| process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], | ||
| accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use a mnemonic? Isn't that the preferred way of generating accounts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not change this, this was just a listing change. I think we should ignore this until we get there but ye I agree a mnemonic would be better
| *************************************************/ | ||
|  | ||
| function addLiquidity(address token, uint256 amount) public {} | ||
| function addLiquidity(address l1Token, uint256 l1TokenAmount) public payable { | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this all new code? Or is it all copied? Or is it a mix? If a mix, can you comment on the parts that you have changed (throughout the file)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's copied but changed to include the new mapping structure. the v1 version of this did not specify the l1Token (one token per pool). the changes therefore are simply to define the l1Token within the mapping. the other small change is the mint logic is now called on the external contract, rather than on this as the LPtoken is external.
| ExpandedERC20 lpToken = new ExpandedERC20( | ||
| append("Across ", IERC20Metadata(l1Token).name(), " LP Token"), // LP Token Name | ||
| append("Av2-", IERC20Metadata(l1Token).symbol(), "-LP"), // LP Token Symbol | ||
| IERC20Metadata(l1Token).decimals() // LP Token Decimals | ||
| ); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor note: we could use a contract like the TokenFactory here down the line so the ERC20 bytecode doesn't need to live in this contract (and thus, we give ourselves more room in the bytecode limit).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a good point. we can make this change if we run out of space. I'll add a comment.
| import "@uma/core/contracts/common/implementation/Testable.sol"; | ||
| import "@uma/core/contracts/common/implementation/Lockable.sol"; | ||
| import "@uma/core/contracts/common/implementation/MultiCaller.sol"; | ||
| import "@uma/core/contracts/common/implementation/ExpandedERC20.sol"; | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: something we might consider for a follow-up. We could swap this out for an ERC20 contract that's optimized for this use case (immutable and singular minter/burner).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point. will add a comment.
        
          
                contracts/HubPool.sol
              
                Outdated
          
        
      | mapping(address => LPToken) public lpTokens; // Mapping of L1TokenAddress to the associated LPToken. | ||
|  | ||
| constructor(address timerAddress) Testable(timerAddress) {} | ||
| event LiquidityAdded(address l1Token, uint256 amount, uint256 lpTokensMinted, address indexed liquidityProvider); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we index the l1Token?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure & done.
        
          
                contracts/HubPool.sol
              
                Outdated
          
        
      |  | ||
| constructor(address timerAddress) Testable(timerAddress) {} | ||
| event LiquidityAdded(address l1Token, uint256 amount, uint256 lpTokensMinted, address indexed liquidityProvider); | ||
| event LiquidityRemoved(uint256 amount, uint256 lpTokensBurnt, address indexed liquidityProvider); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this include the l1Token?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good catch, it should. done and indexed
| } | ||
|  | ||
| // Added to enable the BridgePool to receive ETH. used when unwrapping Weth. | ||
| receive() external payable {} | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we revert if this comes from an address that is not the WETH contract?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's an interesting idea but its somewhat inconsistant. we dont prevent users from sending tokens so why should we prevent them from sending eth?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you're saying. ETH transfers work differently, so I would argue it's more likely to send ETH accidentally. However, this would incur a slight gas cost, so it probably isn't worth the cost of the check.
Co-authored-by: Matt Rice <matthewcrice32@gmail.com>
Co-authored-by: Matt Rice <matthewcrice32@gmail.com>
* chore: formatting fix (#1) Signed-off-by: Matt Rice <matthewcrice32@gmail.com> * Arbitrum, Ink, Mode, ZkSync * chore: Deploy Blast SpokePool implementation (#3) * chore: Deploy AlephZero SpokePool implementation (#6) * chore: Deploy WorldChain SpokePool implementation (#5) * deploy base lisk eth redstone scroll soneium spoke implementations (#4) Signed-off-by: Matt Rice <matthewcrice32@gmail.com> Signed-off-by: bennett <bennett@umaproject.org> Co-authored-by: Matt Rice <matthewcrice32@gmail.com> * chore: add deployments for linea, optimism, polygon, and zora (#7) Signed-off-by: Matt Rice <matthewcrice32@gmail.com> * fix(test): Require transfer to msg.sender on fill (#8) * fix(artifacts): update artifacts with implementation address Signed-off-by: bennett <bennett@umaproject.org> --------- Signed-off-by: Matt Rice <matthewcrice32@gmail.com> Signed-off-by: bennett <bennett@umaproject.org> Co-authored-by: nicholaspai <npai.nyc@gmail.com> Co-authored-by: Paul <108695806+pxrl@users.noreply.github.com> Co-authored-by: bmzig <57361391+bmzig@users.noreply.github.com> Co-authored-by: bennett <bennett@umaproject.org>
This PR adds liquidity addition/removal logic.