I'm trying to create a simple Vyper contract that withdraws my USDC
and converts this to a token that's passed through the argument list in the swap_usdc
method.
I approve this contract to withdraw my USDC
however, when attempting to call the swap_usdc
method, the contract reverts.
I have no clue as to why and running out of ideas. Could it be that I'm not calling the UniswapV3 interfaces correctly? Any other ideas/help much appreciated.
Here are my
Input parameters: 5000000
(5 USDC)
Outtoken address: 0x8505b9d2254A7Ae468c0E9dd10Ccea3A837aef5c
(Compound on Polygon)
Failed tx hash: 0x33db3c307813a307fd9086b41d3e3a92a5d601ba0a5c5b7c679cf32dbe9e2584
Code:
from vyper.interfaces import ERC20
USDC: constant(address) = 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174
UNIV3_ROUTER: constant(address) = 0xE592427A0AEce92De3Edee1F18E0157C05861564
struct ExactInputSingleParams: # ISwapRouter
tokenIn: address
tokenOut: address
fee: uint256
recipient: address
deadline: uint256
amountIn: uint256
amountOutMinimum: uint256
sqrtPriceLimitX96: uint256
struct ExactOutputSingleParams: # ISwapRouter
tokenIn: address
tokenOut: address
fee: uint256
recipient: address
deadline: uint256
amountOut: uint256
amountInMaximum: uint256
sqrtPriceLimitX96: uint256
interface ISwapRouter:
# @uniswap-v3-periphery/SwapRouter.sol
def exactInputSingle(params: ExactInputSingleParams) -> uint256: payable
def exactOutputSingle(params: ExactOutputSingleParams) -> uint256: payable
def refundETH(): nonpayable
@external
def swap_usdc(amount_in: uint256, outtoken: address, desination: address):
ERC20(USDC).transferFrom(msg.sender,self,amount_in)
result: uint256 = ISwapRouter(UNIV3_ROUTER).exactInputSingle(
ExactInputSingleParams({
tokenIn: USDC,
tokenOut: outtoken,
fee: convert(3000, uint256),
recipient: desination,
deadline: block.timestamp,
amountIn: amount_in,
amountOutMinimum: 0,
sqrtPriceLimitX96: empty(uint256)
})
)
Even when I update code to below based on feedback from people below, i still get wrong keccak value
from vyper.interfaces import ERC20
UNISWAP: constant(address) = 0x93bcDc45f7e62f89a8e901DC4A0E2c6C427D9F25 #0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D ethereum
@external
def swap(_from: address, _to: address, _amount: uint256, _minout: uint256) -> Bytes[32]:
ERC20(_from).transferFrom(msg.sender,self,_amount)
ERC20(_from).approve(UNISWAP, _amount)
result: Bytes[32] = raw_call(
UNISWAP,
concat(method_id("exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160))"),
convert(_from, bytes32),
convert(_to, bytes32),
convert(3000, bytes32),
convert(msg.sender, bytes32),
convert(block.timestamp, bytes32),
convert(_amount, bytes32),
convert(_minout, bytes32),
convert(0, bytes32)
),
is_delegate_call=False,
max_outsize=32
)
assert convert(result,uint256) >= _minout, "less"
return result
approve
function on the USDC token contract to allow your contract to spend the tokens?