uint256 input in RemixIDE - solidity

I'm trying to learn developing my first smart contract in order to use flash loans on aave. I have a problem regarding the amount input for the transaction.
I've a function asking for the amount of token I need and the type is uint256. When I type 10 I only receive 0.0000000000000001 by the flash loan. Why? Maybe it's a stupid question but I'm not understanding what's wrong.
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
import { FlashLoanReceiverBase } from "./FlashLoanReceiverBase.sol";
import { ILendingPool, ILendingPoolAddressesProvider, IERC20 } from "./Interfaces.sol";
import { SafeMath } from "./Libraries.sol";
import "./Ownable.sol";
/*
* A contract that executes the following logic in a single atomic transaction:
*
*
*/
contract BatchFlashDemo is FlashLoanReceiverBase, Ownable {
ILendingPoolAddressesProvider provider;
using SafeMath for uint256;
uint256 flashDaiAmt0;
address lendingPoolAddr;
// mumbai reserve asset addresses
address mumbaiDai = 0x001B3B4d0F3714Ca98ba10F6042DaEbF0B1B7b6F;
// intantiate lending pool addresses provider and get lending pool address
constructor(ILendingPoolAddressesProvider _addressProvider) FlashLoanReceiverBase(_addressProvider) public {
provider = _addressProvider;
lendingPoolAddr = provider.getLendingPool();
}
/**
This function is called after your contract has received the flash loaned amount
*/
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
)
external
override
returns (bool)
{
/*
*
*
*/
// Approve the LendingPool contract allowance to *pull* the owed amount
// i.e. AAVE V2's way of repaying the flash loan
for (uint i = 0; i < assets.length; i++) {
uint amountOwing = amounts[i].add(premiums[i]);
IERC20(assets[i]).approve(address(_lendingPool), amountOwing);
}
return true;
}
/*
* This function is manually called to commence the flash loans sequence
*/
function executeFlashLoans(uint256 _flashDaiAmt0) public onlyOwner {
address receiverAddress = address(this);
// the various assets to be flashed
address[] memory assets = new address[](1);
assets[0] = mumbaiDai;
// the amount to be flashed for each asset
uint256[] memory amounts = new uint256[](1);
amounts[0] = _flashDaiAmt0;
flashDaiAmt0 = _flashDaiAmt0;
// 0 = no debt, 1 = stable, 2 = variable
uint256[] memory modes = new uint256[](1);
modes[0] = 0;
address onBehalfOf = address(this);
bytes memory params = "";
uint16 referralCode = 0;
_lendingPool.flashLoan(
receiverAddress,
assets,
amounts,
modes,
onBehalfOf,
params,
referralCode
);
}
/*
* Rugpull all ERC20 tokens from the contract
*/
function rugPull() public payable onlyOwner {
// withdraw all ETH
msg.sender.call{ value: address(this).balance }("");
// withdraw all x ERC20 tokens
IERC20(mumbaiDai).transfer(msg.sender, IERC20(mumbaiDai).balanceOf(address(this)));
}
}
I'm deploying passing this address as parameter:
0x178113104fEcbcD7fF8669a0150721e231F0FD4B
it is the Lending Pool Addresses Provider contract taken from here: https://docs.aave.com/developers/v/2.0/deployed-contracts/matic-polygon-market.
When I try asking for more than 1000tokens I get the error. Hope this helps to reproduce.

EVM doesn't support decimal numbers. So a common approach is to declare a number of decimals in the contract, and then include them with the stored values.
Example:
When a contract uses 2 decimals, value of 1 is stored as 100.
Aave protocol works with ERC20 tokens, where the standard defines a function named decimals() to return a number of decimal places.

Related

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!

Member "push" is not available in struct ... memory outside of storage

Below is the contract:
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.12;
// Contracts
pragma experimental ABIEncoderV2;
contract test{
mapping(address => address) public managers;
struct tokenInfo{
address token;
uint256 decimals;
uint256 amount;
}
struct recordInfo{
uint time;
tokenInfo[] tokens;
}
mapping(address => mapping(uint => recordInfo)) public record_List;
function claim(address pool) public {
address manager = address(0);
require(managers[pool] != manager,"claim is not manager"); // this `require` is necessary, if delete it, cannot compile, why?
//record
recordInfo storage record; // claim `storage`, compile succeed
delete record.time;
delete record.tokens;
record.time = block.timestamp;
for( uint i = 0;i < 2;i++){
uint balance;
tokenInfo memory token;
token.token = address(0);
token.amount = balance;
token.decimals = 18;
record.tokens.push(token);
}
record_List[pool][2] = record;
}
}
then I change the recordInfo storage record to recordInfo memory record;, the contract cannot compile in the remix
function claim(address pool) public {
address manager = address(0);
require(managers[pool] != manager,"claim is not manager"); // this `require` is necessary, if delete it, cannot compile, why?
//record
recordInfo memory record; // claim `memory`, cannot compile
delete record.time;
delete record.tokens;
record.time = block.timestamp;
for( uint i = 0;i < 2;i++){
uint balance;
tokenInfo memory token;
token.token = address(0);
token.amount = balance;
token.decimals = 18;
record.tokens.push(token);
}
record_List[pool][2] = record;
}
and here is the error msg :
from solidity:
tests/testuint.sol:38:13: TypeError: Member "push" is not available in struct test.tokenInfo memory[] memory outside of storage.
record.tokens.push(token);
^----------------^
Why claimed storage here okay instead of memory?
can here claim it to memory?
If storage is used, why need the require?
Why claimed storage here okay instead of memory?
This happened because push() method can use only for object memorized in storage. Thus, for object stored in memory you can only insert data specifying index.
More information about this topic on documentation.
Can here claim it to memory?
No, you cannot claim it changing storage position from storage to memory, because of all records are stored into storage space and you cannot update or delete their data if you change memory position.
If storage is used, why need the require?
I think that it's a bug about compiler 0.6. Thus, if you try to change Solidity compiler from 0.6 to 0.8, the issues will show itself. Irrespective of this, the compiler say you that the record (declared into claim() method) don't point to any data present into record_List mapping. In a simple words, it wasn't initialized. In your case, you can consider to retrieve a specific element from record_List mapping and then you do delete and update operations.
An example:
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.6.12;
// Contracts
pragma experimental ABIEncoderV2;
contract test{
mapping(address => address) public managers;
struct tokenInfo{
address token;
uint256 decimals;
uint256 amount;
}
struct recordInfo{
uint time;
tokenInfo[] tokens;
}
mapping(address => mapping(uint => recordInfo)) public record_List;
function claim(address pool, uint idRecord) public {
address manager = address(0);
require(managers[pool] != manager,"claim is not manager");
// NOTE: I retrieve a specific element from record_List mapping using pool and idRecord parameters for querying the mapping
recordInfo storage record = record_List[pool][idRecord];
delete record.time;
delete record.tokens;
record.time = block.timestamp;
for( uint i = 0;i < 2;i++){
uint balance;
tokenInfo memory token;
token.token = address(0);
token.amount = balance;
token.decimals = 18;
record.tokens.push(token);
}
record_List[pool][2] = record;
}
}

'Gas Estimation Failed' Error when trying to deploy a contract on remix to the Ganache test net

This is what the error reads:
Gas estimation errored with the following message (see below). The
transaction execution will likely fail. Do you want to force sending?
Internal JSON-RPC error. { "message": "Returned error: project ID does
not have access to archive state", "code": -32000, "data": { "stack":
"Error: Returned error: project ID does not have access to archive
state\n at Object.ErrorResponse
(/usr/local/lib/node_modules/ganache-cli/build/ganache-core.node.cli.js:55:2110625)\n
at a
(/usr/local/lib/node_modules/ganache-cli/build/ganache-core.node.cli.js:55:2108932)\n
at
/usr/local/lib/node_modules/ganache-cli/build/ganache-core.node.cli.js:55:2093154\n
at runMicrotasks ()\n at processTicksAndRejections
(internal/process/task_queues.js:95:5)", "name": "Error" } }
I have made the settings for deployment on remix:
Injected Web 3
pragma solidity ^0.5.0;
pragma experimental ABIEncoderV2;
interface Structs {
struct Val {
uint256 value;
}
enum ActionType {
Deposit, // supply tokens
Withdraw, // borrow tokens
Transfer, // transfer balance between accounts
Buy, // buy an amount of some token (externally)
Sell, // sell an amount of some token (externally)
Trade, // trade tokens against another account
Liquidate, // liquidate an undercollateralized or expiring account
Vaporize, // use excess tokens to zero-out a completely negative account
Call // send arbitrary data to an address
}
enum AssetDenomination {
Wei // the amount is denominated in wei
}
enum AssetReference {
Delta // the amount is given as a delta from the current value
}
struct AssetAmount {
bool sign; // true if positive
AssetDenomination denomination;
AssetReference ref;
uint256 value;
}
struct ActionArgs {
ActionType actionType;
uint256 accountId;
AssetAmount amount;
uint256 primaryMarketId;
uint256 secondaryMarketId;
address otherAddress;
uint256 otherAccountId;
bytes data;
}
struct Info {
address owner; // The address that owns the account
uint256 number; // A nonce that allows a single address to control many accounts
}
struct Wei {
bool sign; // true if positive
uint256 value;
}
}
contract DyDxPool is Structs {
function getAccountWei(Info memory account, uint256 marketId) public view returns (Wei memory);
function operate(Info[] memory, ActionArgs[] memory) public;
}
/**
* #dev Interface of the ERC20 standard as defined in the EIP. Does not include
* the optional functions; to access them see `ERC20Detailed`.
*/
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
}
contract DyDxFlashLoan is Structs {
DyDxPool pool = DyDxPool(0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e);
address public WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
mapping(address => uint256) public currencies;
constructor() public {
currencies[WETH] = 1;
}
modifier onlyPool() {
require(
msg.sender == address(pool),
"FlashLoan: could be called by DyDx pool only"
);
_;
}
function tokenToMarketId(address token) public view returns (uint256) {
uint256 marketId = currencies[token];
require(marketId != 0, "FlashLoan: Unsupported token");
return marketId - 1;
}
// the DyDx will call `callFunction(address sender, Info memory accountInfo, bytes memory data) public` after during `operate` call
function flashloan(address token, uint256 amount, bytes memory data)
internal
{
IERC20(token).approve(address(pool), amount + 1);
Info[] memory infos = new Info[](1);
ActionArgs[] memory args = new ActionArgs[](3);
infos[0] = Info(address(this), 0);
AssetAmount memory wamt = AssetAmount(
false,
AssetDenomination.Wei,
AssetReference.Delta,
amount
);
ActionArgs memory withdraw;
withdraw.actionType = ActionType.Withdraw;
withdraw.accountId = 0;
withdraw.amount = wamt;
withdraw.primaryMarketId = tokenToMarketId(token);
withdraw.otherAddress = address(this);
args[0] = withdraw;
ActionArgs memory call;
call.actionType = ActionType.Call;
call.accountId = 0;
call.otherAddress = address(this);
call.data = data;
args[1] = call;
ActionArgs memory deposit;
AssetAmount memory damt = AssetAmount(
true,
AssetDenomination.Wei,
AssetReference.Delta,
amount + 1
);
deposit.actionType = ActionType.Deposit;
deposit.accountId = 0;
deposit.amount = damt;
deposit.primaryMarketId = tokenToMarketId(token);
deposit.otherAddress = address(this);
args[2] = deposit;
pool.operate(infos, args);
}
}
contract Flashloan is DyDxFlashLoan {
uint256 public loan;
constructor() public payable {
(bool success, ) = WETH.call.value(msg.value)("");
require(success, "fail to get weth");
}
function getFlashloan(address flashToken, uint256 flashAmount) external {
uint256 balanceBefore = IERC20(flashToken).balanceOf(address(this));
bytes memory data = abi.encode(flashToken, flashAmount, balanceBefore);
flashloan(flashToken, flashAmount, data); // execution goes to `callFunction`
}
function callFunction(
address, /* sender */
Info calldata, /* accountInfo */
bytes calldata data
) external onlyPool {
(address flashToken, uint256 flashAmount, uint256 balanceBefore) = abi
.decode(data, (address, uint256, uint256));
uint256 balanceAfter = IERC20(flashToken).balanceOf(address(this));
require(
balanceAfter - balanceBefore == flashAmount,
"contract did not get the loan"
);
loan = balanceAfter;
// Use the money here!
}
}

Type error: Member not found or visible in unit256

I have this crowdfunding platform that was initially using SafeMath library. And since is deprecated I'm looking for a workaround to make it compile and I'm getting a compilation error with remix in line 131:
contributions[msg.sender] = contributions[msg.sender].add(msg.value);
Here you have the whole contract code, it's a platform where you can create projects and raise funds:
// We will be using Solidity version 0.6.0
pragma solidity 0.6.0;
// Importing OpenZeppelin's SafeMath Implementation
//import 'https://github.com/OpenZeppelin/openzeppelin-solidity/contracts/math/SafeMath.sol';
//import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/SafeMathMock.sol";
//import "#openzeppelin/contracts/utils/math/SafeMath.sol";
contract Crowdfunding {
// using SafeMath for uint256;
// List of existing projects
Project[] private projects;
// Event that will be emitted whenever a new project is started
event ProjectStarted(
address contractAddress,
address projectStarter,
string projectTitle,
string projectDesc,
uint deadline,
uint goalAmount
);
/** #dev Function to start a new project.
* #param title Title of the project to be created
* #param description Brief description about the project
* #param durationInDays Project deadline in days
* #param amountToRaise Project goal in wei
*/
function startProject(
string calldata title,
string calldata description,
uint durationInDays,
uint amountToRaise
) external {
// uint raiseUntil = now.add(durationInDays.mul(1 days));
uint durationInSeconds = durationInDays * 1 days;
// Check that the result of division (inverse operation to multiplication) is the original number.
// If it's not, throw an exception, because the multiplication overflowed.
require(durationInSeconds / durationInDays == 1 days, 'Multiplication overflow');
uint raiseUntil = block.timestamp + durationInSeconds;
// Check that the result of subtraction (inverse operation to addition) is the original number.
// If it's not, throw an exception, because the addition overflowed.
require(raiseUntil - block.timestamp == durationInSeconds, 'Addition overflow');
Project newProject = new Project(msg.sender, title, description, raiseUntil, amountToRaise);
projects.push(newProject);
emit ProjectStarted(
address(newProject),
msg.sender,
title,
description,
raiseUntil,
amountToRaise
);
}
/** #dev Function to get all projects' contract addresses.
* #return A list of all projects' contract addreses
*/
function returnAllProjects() external view returns(Project[] memory){
return projects;
}
}
contract Project {
// not using SafeMath for uint256;
// Data structures
enum State {
Fundraising,
Expired,
Successful
}
// State variables
address payable public creator;
uint public amountGoal; // required to reach at least this much, else everyone gets refund
uint public completeAt;
uint256 public currentBalance;
uint public raiseBy;
string public title;
string public description;
State public state = State.Fundraising; // initialize on create
mapping (address => uint) public contributions;
// Event that will be emitted whenever funding will be received
event FundingReceived(address contributor, uint amount, uint currentTotal);
// Event that will be emitted whenever the project starter has received the funds
event CreatorPaid(address recipient);
// Modifier to check current state
modifier inState(State _state) {
require(state == _state);
_;
}
// Modifier to check if the function caller is the project creator
modifier isCreator() {
require(msg.sender == creator);
_;
}
constructor
(
address payable projectStarter,
string memory projectTitle,
string memory projectDesc,
uint fundRaisingDeadline,
uint goalAmount
) public {
creator = projectStarter;
title = projectTitle;
description = projectDesc;
amountGoal = goalAmount;
raiseBy = fundRaisingDeadline;
currentBalance = 0;
}
/** #dev Function to fund a certain project.
*/
function contribute() external inState(State.Fundraising) payable {
require(msg.sender != creator);
contributions[msg.sender] = contributions[msg.sender].add(msg.value);
currentBalance = currentBalance.add(msg.value);
emit FundingReceived(msg.sender, msg.value, currentBalance);
checkIfFundingCompleteOrExpired();
}
/** #dev Function to change the project state depending on conditions.
*/
function checkIfFundingCompleteOrExpired() public {
if (currentBalance >= amountGoal) {
state = State.Successful;
payOut();
} else if (now > raiseBy) {
state = State.Expired;
}
completeAt = now;
}
/** #dev Function to give the received funds to project starter.
*/
function payOut() internal inState(State.Successful) returns (bool) {
uint256 totalRaised = currentBalance;
currentBalance = 0;
if (creator.send(totalRaised)) {
emit CreatorPaid(creator);
return true;
} else {
currentBalance = totalRaised;
state = State.Successful;
}
return false;
}
/** #dev Function to retrieve donated amount when a project expires.
*/
function getRefund() public inState(State.Expired) returns (bool) {
require(contributions[msg.sender] > 0);
uint amountToRefund = contributions[msg.sender];
contributions[msg.sender] = 0;
if (!msg.sender.send(amountToRefund)) {
contributions[msg.sender] = amountToRefund;
return false;
} else {
currentBalance = currentBalance.sub(amountToRefund);
}
return true;
}
/** #dev Function to get specific information about the project.
* #return Returns all the project's details
*/
function getDetails() public view returns
(
address payable projectStarter,
string memory projectTitle,
string memory projectDesc,
uint256 deadline,
State currentState,
uint256 currentAmount,
uint256 goalAmount
) {
projectStarter = creator;
projectTitle = title;
projectDesc = description;
deadline = raiseBy;
currentState = state;
currentAmount = currentBalance;
goalAmount = amountGoal;
}
}
The Using X for Y expression extends the Y datatype with functions of the X library.
In case of using SafeMath for uint256, it allows to use the functions defined in SafeMath (such as add()) on uint256 variables.
Specifically, function add() in SafeMath checks whether the addition would overflow the 256bit unsigned integer. If it did overflow, it throws an exception. If it didn't overflow, it returns the result of the addition.
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
You can achieve the same result with this snippet:
uint256 contribution = contributions[msg.sender] + msg.value; // c = a + b
require(contribution >= contributions[msg.sender]); // require(c >= a)
contributions[msg.sender] = contribution; // return c
If you switch to Solidity 0.8+, this is not needed, because since version 0.8.0, Solidity performs the overflow check automatically and reverts if an overflow/underflow would occur. So it would be sufficient to use just this snippet:
// safe in Solidity 0.8+, unsafe in older versions
contributions[msg.sender] += msg.value;
Arithmetic operations revert on underflow and overflow. You can use unchecked { ... } to use the previous wrapping behaviour.
Source: docs

When deploying a smart contract, isn't the "owner" of the contract (by default) the one who deploys it?

I am trying to use a function in a flashloan contract that uses the onlyOwner modifier. When I send the flashloan transaction, I get returned the error: "caller is not the owner".
I am using the same account that I used to create the contract when running this flash loan, so I'm not sure why it's not recognizing me as the owner.
You can see here that it is the same address to create the contract and to send the failed transaction.
https://kovan.etherscan.io/address/0x91109bde85e0ab631d1983ce07b910ce4e99078a
Click on the first transaction there ^^ to see the error message.
code of onlyOwner modifier: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol
Contract file
pragma solidity ^0.6.6;
import "./aave/FlashLoanReceiverBaseV2.sol";
import "../../interfaces/v2/ILendingPoolAddressesProviderV2.sol";
import "../../interfaces/v2/ILendingPoolV2.sol";
contract FlashloanV2 is FlashLoanReceiverBaseV2, Withdrawable {
constructor(address _addressProvider) FlashLoanReceiverBaseV2(_addressProvider) public {}
/**
* #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.
//
// 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 (uint i = 0; i < assets.length; i++) {
uint amountOwing = amounts[i].add(premiums[i]);
IERC20(assets[i]).approve(address(LENDING_POOL), amountOwing);
}
for (uint i = 0; i < assets.length; i++) {
withdraw(assets[i]);
}
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 1000000000000000000 wei (1 ether) worth of `_asset`
*/
function flashloan(address _asset) public onlyOwner {
bytes memory data = "";
uint amount = 1 ether;
address[] memory assets = new address[](1);
assets[0] = _asset;
uint256[] memory amounts = new uint256[](1);
amounts[0] = amount;
_flashloan(assets, amounts);
}
}
Withdrawable.sol (where withdraw() function comes from)
pragma solidity ^0.6.6;
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
import "#openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
/**
Ensures that any contract that inherits from this contract is able to
withdraw funds that are accidentally received or stuck.
*/
contract Withdrawable is Ownable {
using SafeERC20 for ERC20;
address constant ETHER = address(0);
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 == ETHER) {
address self = address(this); // workaround for a possible solidity bug
assetBalance = self.balance;
msg.sender.transfer(assetBalance);
} else {
assetBalance = ERC20(_assetAddress).balanceOf(address(this));
ERC20(_assetAddress).safeTransfer(msg.sender, assetBalance);
}
emit LogWithdraw(msg.sender, _assetAddress, assetBalance);
}
}