Error during calling function in smart contract - solidity

I need some understanding why I get errors in the following code. I try to call function getAmountOutMin to get the amount of particular token(_tokenOut) I can buy (amountOutMins) on _amountIn of token _tokenIn. But regardless of amount I specify in _amountIn(for instance, I specify 10000000000000000 WEI, that's about 0.01 WETH) I get the error.
call to Uniswap.getAmountOutMin errored: execution reverted
As I token_in I specify 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6 address(WETH in Goerli), token_out = 0x78c26A88c19ae0311e0121f7350735b842AFFd41.
I do need some help to understand what I'm doing wrong
pragma solidity ^0.8.7;
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import "hardhat/console.sol";
interface IUniswapV2Router {
function getAmountsOut(uint256 amountIn, address[] memory path)
external
view
returns (uint256[] memory amounts);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
uint256 deadline
) external returns (uint256[] memory amounts);
}
contract Uniswap {
address private constant uniswap_goerli = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
address private constant WETH_Goerli = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6;
address private constant ETH_Goerli = 0x8d27431c473E83611847D195d325972e80D1F4c1;
///call via web3
function approve_for_uniswap(uint _amount_to_send) public payable{
// IERC20(ETH_Goerli).approve(address(this),_amount_to_send);
// IERC20(ETH_Goerli).transfer(address(this),_amount_to_send);
IERC20(ETH_Goerli).approve(uniswap_goerli,_amount_to_send);
}
function _swap_token(address _token_in,address _token_out,uint _amountIn,uint _amountOutMin,address _to) external{
address[] memory path;
if (_token_in==WETH_Goerli || _token_out == WETH_Goerli){
path = new address[](2);
path[0]=_token_in;
path[1] = _token_out;}
else {
path = new address[](3);
path[0] = _token_in;
path[1] = WETH_Goerli;
path[2] = _token_out;
}
IUniswapV2Router(uniswap_goerli).swapExactTokensForTokens(_amountIn, _amountOutMin, path, _to, block.timestamp);
}
function getAmountOutMin(address _tokenIn, address _tokenOut, uint256 _amountIn) external view returns (uint256) {
address[] memory path;
if (_tokenIn == WETH_Goerli || _tokenOut == WETH_Goerli) {
path = new address[](2);
path[0] = _tokenIn;
path[1] = _tokenOut;
} else {
path = new address[](3);
path[0] = _tokenIn;
path[1] = WETH_Goerli;
path[2] = _tokenOut;
}
uint256[] memory amountOutMins = IUniswapV2Router(uniswap_goerli).getAmountsOut(_amountIn, path);
return amountOutMins[path.length -1];}```

Related

How to create a withdraw function

I created a basic contract for crowdfunding. But cannot figure out how to create a withdraw function.
Withdraw function will transfer a campaign's collected funds to the campaign's owner. This is my full crowdfunding contract:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;
contract CrowdFunding {
event testConditon(
uint256 deadline,
uint256 currentTimeInMs,
uint256 diff,
bool condition
);
struct Campaign {
address payable owner;
string title;
string description;
uint256 target;
uint256 deadline;
uint256 amountCollected;
string image;
address[] donators;
uint256[] donations;
}
mapping(uint256 => Campaign) public campaigns;
uint256 public numberOfCampaigns = 0;
function createCampaign(
address _owner,
string memory _title,
string memory _description,
uint256 _target,
uint256 _deadline,
string memory _image
) public returns (uint256) {
Campaign storage campaign = campaigns[numberOfCampaigns];
uint256 currentTimeInMs = block.timestamp * 1000;
emit testConditon(
_deadline,
currentTimeInMs,
_deadline - currentTimeInMs,
_deadline > currentTimeInMs
);
require(
_deadline > currentTimeInMs,
"The deadline must be in the future"
);
campaign.owner = payable(_owner);
campaign.title = _title;
campaign.description = _description;
campaign.target = _target;
campaign.deadline = _deadline;
campaign.image = _image;
campaign.amountCollected = 0;
numberOfCampaigns++;
return numberOfCampaigns - 1;
}
function donateToCampaign(uint256 _id) public payable {
uint256 amount = msg.value;
Campaign storage campaign = campaigns[_id];
campaign.donators.push(msg.sender);
campaign.donations.push(amount);
(bool sent, ) = payable(campaign.owner).call{value: amount}("");
if (sent) {
campaign.amountCollected += amount;
}
}
function getDonators(uint256 _id)
public
view
returns (address[] memory, uint256[] memory)
{
return (campaigns[_id].donators, campaigns[_id].donations);
}
function getCampaigns() public view returns (Campaign[] memory) {
Campaign[] memory allCampaigns = new Campaign[](numberOfCampaigns);
for (uint256 i = 0; i < numberOfCampaigns; i++) {
Campaign storage item = campaigns[i];
allCampaigns[i] = item;
}
return allCampaigns;
}
function withdraw(uint256 _id) public {
Campaign storage campaign = campaigns[_id];
require(
campaign.amountCollected >= campaign.target,
"The campaign has not reached its target"
);
//deadline has passed
// require(
// campaign.deadline < block.timestamp * 1000,
// "The deadline has not passed yet"
// );
require(
campaign.owner == msg.sender,
"Only the owner of the campaign can withdraw the funds"
);
campaign.owner.transfer(campaign.amountCollected);
campaign.amountCollected = 0;
}
}
I have no idea how to solve this issue.
Looks like you are missing the payable keyword to trigger the token transfer. Try this:
function withdraw(uint256 _id) public {
Campaign storage campaign = campaigns[_id];
(bool success, ) = payable(campaign.owner).call{value: campaign.amountCollected}("");
require(success, "Withdrawal failure");
campaign.amountCollected = 0;
}
Warning: this function and your function are having a reentrency vulnerability.

Error: execution reverted: SafeERC20: low-level call failed with AAVE

Don't know if here is the best place but i'm in despair. I have this flashloan code:
pragma solidity ^0.6.6;
import "#aave/protocol-v2/contracts/flashloan/base/FlashLoanReceiverBase.sol";
import "#aave/protocol-v2/contracts/interfaces/ILendingPoolAddressesProvider.sol";
import "#aave/protocol-v2/contracts/interfaces/ILendingPool.sol";
import "#uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import {SafeERC20} from "#aave/protocol-v2/contracts/dependencies/openzeppelin/contracts/SafeERC20.sol";
//import "#openzeppelin/contracts/interfaces/IERC20.sol";
contract FlashloanV2 is FlashLoanReceiverBase {
using SafeERC20 for IERC20;
constructor(
ILendingPoolAddressesProvider _addressProvider,
address _routerA,
address _routerB,
address _token,
address _WETH
) public FlashLoanReceiverBase(_addressProvider)
{
owner = msg.sender;
routerA = _routerA;
routerB = _routerB;
token = _token;
WETH = _WETH;
}
address owner;
address routerA;
address routerB;
address token;
address WETH;
modifier onlyOwner{
require(msg.sender == owner, "Hey hey hey you can't use this function");
_;
}
/**
* #dev This function must be called only be the LENDING_POOL and takes care of repaying
* active debt positions, migrating collateral and incurring new V2 debt token debt.
*
* #param assets The array of flash loaned assets used to repay debts.
* #param amounts The array of flash loaned asset amounts used to repay debts.
* #param premiums The array of premiums incurred as additional debts.
* #param initiator The address that initiated the flash loan, unused.
* #param params The byte array containing, in this case, the arrays of aTokens and aTokenAmounts.
*/
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external override returns (bool) {
//
// This contract now has the funds requested.
// Your logic goes here.
//
address[] memory path = new address[](2);
path[0] = token;
path[1] = WETH;
address[] memory path2 = new address[](2);
path2[0] = WETH;
path2[1] = token;
uint balance = address(this).balance;
IERC20(WETH).approve(routerA, balance);
IUniswapV2Router02(routerA).swapExactTokensForTokensSupportingFeeOnTransferTokens(
balance,
0,
path2,
address(this),
block.timestamp + 1200
);
uint tokenBalance = IERC20(token).balanceOf(address(this));
IERC20(token).approve(routerB, tokenBalance);
IUniswapV2Router02(routerB).swapExactTokensForTokensSupportingFeeOnTransferTokens(
tokenBalance,
0,
path,
address(this),
block.timestamp + 1200
);
//payable(owner).transfer(address(this).balance - (amounts[0] + premiums[0]));
// At the end of your logic above, this contract owes
// the flashloaned amounts + premiums.
// Therefore ensure your contract has enough to repay
// these amounts.
// Approve the LendingPool contract allowance to *pull* the owed amount
for (uint256 i = 0; i < assets.length; i++) {
uint256 amountOwing = amounts[i].add(premiums[i]);
IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);
}
return true;
}
function _flashloan(address[] memory assets, uint256[] memory amounts)
internal
{
address receiverAddress = address(this);
address onBehalfOf = address(this);
bytes memory params = "";
uint16 referralCode = 0;
uint256[] memory modes = new uint256[](assets.length);
// 0 = no debt (flash), 1 = stable, 2 = variable
for (uint256 i = 0; i < assets.length; i++) {
modes[i] = 0;
}
LENDING_POOL.flashLoan(
receiverAddress,
assets,
amounts,
modes,
onBehalfOf,
params,
referralCode
);
}
/*
* Flash multiple assets
*/
function flashloan(address[] memory assets, uint256[] memory amounts)
public
onlyOwner
{
_flashloan(assets, amounts);
}
/*
* Flash loan 100000000000000000 wei (0.1 ether) worth of `_asset`
*/
function flashloan(address _asset) public onlyOwner {
bytes memory data = "";
uint256 amount = 50 ether;
address[] memory assets = new address[](1);
assets[0] = _asset;
uint256[] memory amounts = new uint256[](1);
amounts[0] = amount;
_flashloan(assets, amounts);
}
event LogWithdraw(
address indexed _from,
address indexed _assetAddress,
uint amount
);
/**
* #dev Withdraw asset.
* #param _assetAddress Asset to be withdrawn.
*/
function withdraw(address _assetAddress) public onlyOwner {
uint assetBalance;
if (_assetAddress == WETH) {
address self = address(this); // workaround for a possible solidity bug
assetBalance = self.balance;
payable(msg.sender).transfer(assetBalance);
} else {
assetBalance = IERC20(_assetAddress).balanceOf(address(this));
IERC20(_assetAddress).safeTransfer(msg.sender, assetBalance);
}
emit LogWithdraw(msg.sender, _assetAddress, assetBalance);
}
function setter(address _routerA, address _routerB, address _token) external onlyOwner returns(bool){
routerA = _routerA;
routerB = _routerB;
token = _token;
return true;
}
function returnOwner() external view returns(address){
return owner;
}
function returnToken() external view returns(address){
return token;
}
function returnWETH() external view returns(address){
return WETH;
}
fallback() external payable {}
}
I'm receiving SafeERC20: low-level call failed when calling flashloan(). There's something wrong with my approving logic or something else?
The contract is funded with enough to pay the fees. Could someone give a hint? Thank you!

AAVE flash loan borrow more tokens always error at hardhat

I'm using hardhat to doing AAVE flash loan, when I borrow one token, is successful, but borrow > 1 tokens, always error.
* deploy on eth mainnet-fork
flash-loans-test.js
const { ethers } = require("hardhat");
const hre = require("hardhat");
describe("AaveFlashLoans", function () {
it("Excute flashloans", async function () {
const contractAddress = "0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5";
const flashLoansFactory = await ethers.getContractFactory("AaveFlashLoans");
const flashLoans = await flashLoansFactory.deploy(contractAddress);
await flashLoans.deployed();
const token = await ethers.getContractAt("IERC20", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"); //weth
const BALANCE_AMOUNT = ethers.utils.parseEther("2");
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: ["0xf07704777d6bc182bf2c67fbda48913169b84983"],
});
const signer = await ethers.getSigner("0xf07704777d6bc182bf2c67fbda48913169b84983");
await token
.connect(signer)
.transfer(flashLoans.address, BALANCE_AMOUNT);
await flashLoans.myFlashLoanCall();
const balance = await token.balanceOf(flashLoans.address)
console.log(balance);
});
});
AaveFlashLoans.sol
pragma solidity ^0.8.0;
import {SafeMath} from "#openzeppelin/contracts/utils/math/SafeMath.sol";
import {IERC20} from "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import {FlashLoanReceiverBase} from "./FlashLoanReceiverBase.sol";
import {ILendingPoolAddressesProvider} from "./ILendingPoolAddressesProvider.sol";
import "hardhat/console.sol";
contract AaveFlashLoans is FlashLoanReceiverBase {
using SafeMath for uint256;
constructor(ILendingPoolAddressesProvider _addressProvider)
FlashLoanReceiverBase(_addressProvider)
{}
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address,
bytes calldata
) external override returns (bool) {
for (uint256 i = 0; i < assets.length; i++) {
uint256 amountOwing = amounts[i].add(premiums[i]);
IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);
console.log(amounts[i]);
console.log(premiums[i]);
}
return true;
}
function myFlashLoanCall() public {
address receiverAddress = address(this);
address[] memory assets = new address[](1);
assets[0] = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); // weth
uint256[] memory amounts = new uint256[](1);
amounts[0] = 1 ether;
uint256[] memory modes = new uint256[](1);
modes[0] = 0;
address onBehalfOf = address(this);
bytes memory params = "";
uint16 referralCode = 0;
LENDING_POOL.flashLoan(
receiverAddress,
assets,
amounts,
modes,
onBehalfOf,
params,
referralCode
);
}
}
above code is successful
successful image1
successful image2
but when I add 2 tokens, it will error
AaveFlashLoans.sol
pragma solidity ^0.8.0;
import {SafeMath} from "#openzeppelin/contracts/utils/math/SafeMath.sol";
import {IERC20} from "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import {FlashLoanReceiverBase} from "./FlashLoanReceiverBase.sol";
import {ILendingPoolAddressesProvider} from "./ILendingPoolAddressesProvider.sol";
import "hardhat/console.sol";
contract AaveFlashLoans is FlashLoanReceiverBase {
using SafeMath for uint256;
constructor(ILendingPoolAddressesProvider _addressProvider)
FlashLoanReceiverBase(_addressProvider)
{}
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address,
bytes calldata
) external override returns (bool) {
for (uint256 i = 0; i < assets.length; i++) {
uint256 amountOwing = amounts[i].add(premiums[i]);
IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);
console.log(amounts[i]);
console.log(premiums[i]);
}
return true;
}
function myFlashLoanCall() public {
address receiverAddress = address(this);
address[] memory assets = new address[](2);
assets[0] = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); // weth
assets[1] = address(0xdAC17F958D2ee523a2206206994597C13D831ec7); // usdt
uint256[] memory amounts = new uint256[](2);
amounts[0] = 1 ether;
amounts[1] = 1 ether;
uint256[] memory modes = new uint256[](2);
modes[0] = 0;
modes[1] = 0;
address onBehalfOf = address(this);
bytes memory params = "";
uint16 referralCode = 0;
LENDING_POOL.flashLoan(
receiverAddress,
assets,
amounts,
modes,
onBehalfOf,
params,
referralCode
);
}
}
above code is error
error image
Please help, thanks a lot lot lot lot...
Since the USDT token has 6 decimals, by inputting the amount as 1 ether, this corresponds to the amount: 1000000000000 USDT. There is not enough availableLiquidity in the pool to borrow this amount, so this is why the tx is reverting. If you reduce the amount, then it should succeed.

Diagnosis 'web3.exceptions.ContractLogicError: execution reverted' error in a modified contract

Contract #1 is a functioning contract (runs with no issues)
Contract #2 is a modified version of Contract #1 with the following changes:
Modified exchangeRouterAddress from being hardcoded to being passed as an arg to the main function buy().
Brokedown buy() function into smaller functions due to "Stack Too Deep" compiling errors.
Hardcoded the value input from Contract #1
Now I've successfully compiled and deployed Contract #2 but running into error web3.exceptions.ContractLogicError: execution reverted. Please help me spot the cause of this error so that Contract #2 can perform just as Contract #1 without issues. Thanks
Contract #1:
pragma solidity ^0.8.12;
// SPDX-License-Identifier: UNLICENSED
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
}
interface IUniswapV2Router02 is IUniswapV2Router01 {
function swapExactETHForTokensSupportingFeeOnTransferTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable;
function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
}
interface IWETH {
function deposit() external payable;
}
contract ReBuy {
receive() external payable {}
address exchangeRouterAddress = 0x10ED43C718714eb63d5aA57B78B54704E256024E;
function buy(address baseToken, address token) public payable returns (uint256, uint256, uint256, uint256, uint256, uint256) {
uint256[] memory gas = new uint256[](2);
IUniswapV2Router02 exchangeRouter = IUniswapV2Router02(exchangeRouterAddress);
IERC20 _token = IERC20(token);
IERC20 _baseToken = IERC20(baseToken);
address[] memory path = new address[](2);
if(baseToken != exchangeRouter.WETH()) {
path[0] = exchangeRouter.WETH();
path[1] = baseToken;
exchangeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{value: msg.value}(0, path, address(this), block.timestamp + 20);
}
else {
IWETH(baseToken).deposit{value: msg.value}();
}
uint256 amount = _baseToken.balanceOf(address(this));
path = new address[](2);
path[0] = baseToken;
path[1] = token;
uint256 expectedToken = exchangeRouter.getAmountsOut(amount, path)[1];
_baseToken.approve(exchangeRouterAddress, type(uint256).max);
uint256 startGas = gasleft();
exchangeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(amount, 0, path, address(this), block.timestamp + 20);
gas[0] = startGas - gasleft();
uint256 receivedToken = _token.balanceOf(address(this));
path = new address[](2);
path[0] = token;
path[1] = baseToken;
uint256 expectedBaseToken = exchangeRouter.getAmountsOut(receivedToken, path)[1];
_token.approve(exchangeRouterAddress, type(uint256).max);
startGas = gasleft();
exchangeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(receivedToken, 0, path, address(this), block.timestamp + 20);
gas[1] = startGas - gasleft();
uint256 receivedBaseToken = _baseToken.balanceOf(address(this));
return (expectedToken, receivedToken, gas[0], expectedBaseToken, receivedBaseToken, gas[1]);
}
}
Contract #2:
pragma solidity ^0.8.12;
// SPDX-License-Identifier: UNLICENSED
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
}
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
}
interface IUniswapV2Router02 is IUniswapV2Router01 {
function swapExactETHForTokensSupportingFeeOnTransferTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable;
function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
}
interface IWETH {
function deposit() external payable;
}
contract ReBuy {
struct ExchangeResult {
uint256 expected;
uint256 received;
uint256 gas;
}
function deposit(address token, address exchangeRouterAddress) internal {
IUniswapV2Router02 exchangeRouter = IUniswapV2Router02(exchangeRouterAddress);
address[] memory path = new address[](2);
if (token != exchangeRouter.WETH()) {
path[0] = exchangeRouter.WETH();
path[1] = token;
exchangeRouter.swapExactETHForTokensSupportingFeeOnTransferTokens{value: 1000000000000000000}(0, path, address(this), block.timestamp + 20);
}
else {
IWETH(token).deposit{value: 1000000000000000000}();
}
}
function exchangeToken(address fromToken, address toToken, address exchangeRouterAddress, uint256 amount) private returns (uint256, uint256, uint256)
{
IUniswapV2Router02 exchangeRouter = IUniswapV2Router02(exchangeRouterAddress);
uint256 expected;
uint256 received;
uint256 gas;
//uint256[] memory gas = new uint256[](2);
address[] memory path = new address[](2);
IERC20 token = IERC20(fromToken);
path[0] = fromToken;
path[1] = toToken;
expected = exchangeRouter.getAmountsOut(amount, path)[1];
token.approve(exchangeRouterAddress, type(uint256).max);
gas = gasleft();
exchangeRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(amount, 0, path, address(this), block.timestamp + 20);
gas = gas - gasleft();
token = IERC20(toToken);
received = token.balanceOf(address(this));
return (expected, received, gas);
}
function buy(address baseToken, address token, address exchangeRouterAddress) public payable returns (uint256, uint256, uint256, uint256, uint256, uint256)
{
IERC20 _baseToken = IERC20(baseToken);
uint256 amount;
ExchangeResult memory tokenRes;
ExchangeResult memory baseTokenRes;
deposit(baseToken, exchangeRouterAddress);
amount = _baseToken.balanceOf(address(this));
(tokenRes.expected, tokenRes.received, tokenRes.gas) = exchangeToken(baseToken, token, exchangeRouterAddress, amount);
(baseTokenRes.expected, baseTokenRes.received, baseTokenRes.gas) = exchangeToken(token, baseToken, exchangeRouterAddress, tokenRes.received);
// Finally return all results
return (tokenRes.expected, tokenRes.received, tokenRes.gas, baseTokenRes.expected, baseTokenRes.received, baseTokenRes.gas);
}
}
Sample of how I call the buy() function (Contract #2 entry function) in python:
token = '0x67382a3364b97e09f727afb388fe817de18f7a18' # Random token just for test
base_token = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c' # WBNB
router_address = '0x10ED43C718714eb63d5aA57B78B54704E256024E' # Pancake Router
deployed_contract = # Place Contract #2 address after deployment here
deployed_contract_ABI = '[{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"exchangeRouterAddress","type":"address"}],"name":"simulate_txn","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]'
deployed_contract = web3.toChecksumAddress(deployed_contract )
contract = web3.eth.contract(address=deployed_contract , abi=deployed_contract_ABI )
results = contract.functions.buy(base_token , token, router_address ).call()
print(results) # Returns 6 values

UniswapV2 swapExactTokensForETH not working

I have been trying to make a swap using UniSwapV2 at Kovan Testnet, but it seems to keep failing. Does anyone knows what is wrong with my piece of code?
function uniswapSwap(uint256 daiAmount) public payable {
// convert to Wei
uint256 amountIn = daiAmount;
//require(DAI.transferFrom(msg.sender, address(this), amountIn), 'transferFrom failed.');
address kovanDAI = address(0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa);
IERC20 DAI= IERC20(kovanDAI);
address uniswapRouterAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
IUniswapV2Router02 uniswapRouter2 = IUniswapV2Router02(uniswapRouterAddress);
require(DAI.approve(address(uniswapRouter2), amountIn), 'approve failed.');
address[] memory path = new address[](2);
path[0] = address(DAI);
path[1] = uniswapRouter2.WETH();
uint deadline = block.timestamp + 15;
uint[] memory amounts = uniswapRouter.swapExactTokensForETH(daiAmount, 0, path, address(this), deadline);
//emit GetDestAmount(amounts[1]);
}