vyperlang / vyper

Pythonic Smart Contract Language for the EVM
https://vyperlang.org
Other
4.9k stars 801 forks source link

Question about calling payable functions of interface contracts #2560

Closed SebasKoel closed 2 years ago

SebasKoel commented 2 years ago

Hi,

First of all great work you all are doing! I hope to be able to be of help when I'm more familiar with the code.

I do have an issue which I tried to lookup but cannot find the answer to.

I think one of the reasons why Vyper isn't really used yet is because the current state in cryptoland is that all tokens being launched are copy-paste from other contracts. Since I don't really like Java or Javascript I wanted to rewrite a Reflection Token contract in Vyper and open source a repo with Brownie and all tests included. I think creating a copy-paste option with tests and a walkthrough can really boost Vyper and maybe prevent some actually cool projects from failing due to contract issues.

However I'm running into an issue: I want to call an Uniswap function via an interface and cannot figure out how this works.

This is the code:


    interface IUniswapV2Factory:
        def createPair(token_A: address,token_B :address) -> address : view

    interface IUniswapV2Router02:
        def swapExactTokensForETHSupportingFeeOnTransferTokens(
            amountIn: uint256,
            amountOutMin: uint256,
            path: address[2],
            to: address,
            deadline: uint256
        ) : view
        def factory() -> address : pure
        def WETH() -> address : pure
        def addLiquidityETH(
            token: address,
            amountTokenDesired: uint256,
            amountTokenMin: uint256,
            amountETHMin: uint256,
            to: address,
            deadline: uint256
        ) -> (uint256, uint256, uint256): payable

    @external
    def create_pair_and_lp_uniswap() -> bool:
        """
        @notice Creates a WETH/TOKEN pair contract on Uniswap V2
            and deposits the ETH and Tokens in this contract into
            the liquidity pool
        @return True if succesfull, False otherwise 
        """
        assert self.owner == msg.sender, "This function can only be called by the contract owner"
        assert self.uniswap_ready == False, "Uniswap pair and liquidity pool already created"
        uniswap_router_address: address = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
        self.uniswap_contract = IUniswapV2Router02(uniswap_router_address)
        self._approve(self, uniswap_router_address, self.totalSupply)
        self.uniswap_factory = IUniswapV2Factory(self.uniswap_contract.factory())

        pair_address: address = self.uniswap_factory.createPair(self , self.uniswap_contract.WETH())
        contract_balance: uint256 = self.r_balances[self] / (self.r_supply / self.totalSupply)

        amountToken: uint256 = 0
        amountETH: uint256 = 0
        liquidity: uint256 = 0

        #here we need to send a transaction to the Uniswap router with the token and the Eth to go into the liquidity pool.
        # but cannot find how to send along Eth.
        tx = self.uniswap_contract.addLiquidityETH(self, contract_balance,0,0,self.owner,block.timestamp)

        self.uniswap_ready = True

        return True

And this is the working code in Solidity:

`

function openTrading() external onlyOwner() {
    require(!tradingOpen,"trading is already open");
    IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
    uniswapV2Router = _uniswapV2Router;
    _approve(address(this), address(uniswapV2Router), _tTotal);
    uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this), _uniswapV2Router.WETH());
    uniswapV2Router.addLiquidityETH{value: address(this).balance}(address(this),balanceOf(address(this)),0,0,owner(),block.timestamp);
    IERC20(uniswapV2Pair).approve(address(uniswapV2Router), type(uint).max);
}

`

So how do I call a payable function in Vyper?

Thanks in advance

Ohh and a cute animal pic:

squirell

SebasKoel commented 2 years ago

The Factory interface function createpair should've been nonpayable.

As for calling payable functions an extra parameter with value should be added.

Like this:

(amountToken, amountETH, liquidity) = self.uniswap_contract.addLiquidityETH(self, contract_balance, 0, 0, self.owner, block.timestamp, value=self.balance)