Interacting with a Contract from Another Contract Ethereum - ethereum

I have a problem which I'm trying to figure out for a week I think I'm 90% there.
If I deploy a contract MerchantA on a private blockchain and retrieve it's contract address and ABI through the solidity command line solc --abi MerchantA.sol and store it.
Where do I enter this ABI & Address in a brand new contract say inside SendMoneyContract method where calls one of the function of AnimalContract deployed at address 0xrandom.
The material I'm finding online has been to include both solidity source code in the same file but for my case, I can't do it. Reason being MerchantAContract is unique for each deployment [each merchant added gets a unique contract`.
So far, from my understanding, I need to include the MerchantA contract address and ABI. I have no idea how to do it inside the solidity function.

You do not do anything with the ABI.
Let's say you want to call the functionA function on MerchantA FROM MerchantB, all you do is take the interface from MerchantA, an example of an interface of an ERC20 token is:
contract Token {
function totalSupply() constant returns (uint256 supply) {}
function balanceOf(address _owner) constant returns (uint256 balance) {}
function transfer(address _to, uint256 _value) returns (bool success) {}
function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {}
function approve(address _spender, uint256 _value) returns (bool success) {}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
uint public decimals;
string public name;
}
On MerchantB, wherever you want to call functionA, you put the following code:
MerchantA merchantA = MerchantA(0x0000000000000000000000000000000000000000); //Replace 0x000000000000000000000000000000000000000 with the address of MerchantA
merchantA.functionA();
You will need to swap out the interface of MerchantA because you are not using an ERC20 token as well as what function you want to call.

Related

Swapping using Uniswap

Here is my code:
// SPDX-License-Identifier: UNLICENCED
pragma solidity <0.9.0;
interface UniswapInterface{
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
}
interface IERC20{
function balanceOf(address account) external view returns (uint256);
function decimals() external view returns (uint8);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}
contract swapContract{
address public UniSwapRouterAddress = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address public USDCAddress = 0x2fB298BDbeF468638AD6653FF8376575ea41e768;
address public BTCAddress = 0x577D296678535e4903D59A4C929B718e1D575e0A;
IERC20 USDC = IERC20(0x2fB298BDbeF468638AD6653FF8376575ea41e768);
IERC20 BTC = IERC20(0x577D296678535e4903D59A4C929B718e1D575e0A);
UniswapInterface UniSwapRouter = UniswapInterface(UniSwapRouterAddress);
function approveUSDC() public{
USDC.approve(UniSwapRouterAddress, 999**9);
}
function approveBTC() public{
BTC.approve(UniSwapRouterAddress, 999**9);
}
function deposit(uint256 amount) public{
require(amount > 0, "0 is not accepted!");
uint256 allowance = USDC.allowance(msg.sender, address(this));
require(allowance >= amount, "Check USDC allowance");
USDC.transferFrom(msg.sender, address(this), amount);
}
function withdraw() public {
USDC.transfer(msg.sender, USDC.balanceOf(address(this)));
}
function swapUSDC() public {
address[] memory Path = new address[](2);
Path[0] = USDCAddress;
Path[1] = BTCAddress;
UniSwapRouter.swapExactTokensForTokens(
100000000,
0,
Path,
address(this),
block.timestamp + 240
);
}
}
I simply want to swap 1 USDC (its decimal is 8) to BTC on Rinkeby testnetwork.
I tried so many changes like increasing deadline, change in amountIn and amountOutMin but no gain. Also the pool on Uniswap has liquidity.
The error just says:
Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted
I have checked the stackoverflow for answer but could not find a solution
I tried to figure out what the problem might be and realized that most likely there is no such pool.
If you go to the Uniswap UI, you will see that the pool was created only for V3, and you are trying to use the V2 address of router.
There are two ways to solve the problem, the first is to create a liquidity pool in V2 or to make an exchange through V3.

Attn: call to FundMe.getVersion errored: VM execution error. Reverted 0x

How do I fix this issue?
The 0x5f4e... address hardcoded in your getVersion() function doesn't hold any smart contract on the Kovan testnet (link). Even though it has a contract deployed on the mainnet, these environments are separated.
When there's no smart contract on the address, there's nothing to send a response to the internal call. Your code expects an uint256 response from the version() call, so that it can return it from the getVersion().
When it doesn't receive the expected response, it throws an exception, effectively reverting the "main" call.
/ SPDX-License-Identifier: MIT
pragma solidity >=0.6.6 <0.9.0;
interface AggregatorV3Interface {
function decimals()
external view returns (
uint8
);
function description()
external view returns (
string memory
);
function version()
external view returns (
uint256
);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(
uint80 _roundId
)
external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
contract FundMe {
mapping(address =>uint256) public addressToAmountFunded;
function fund() public payable {
addressToAmountFunded[msg.sender] += msg.value;
//What the eth --> usd conversion rate
}
function getVersion() public view returns (uint256) {
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
return priceFeed.version();
}
}
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x8A753747A1Fa494EC906cE90E9f37563A8AF630e);
I checked the address that u used here "0x8A753747A1Fa494EC906cE90E9f37563A8AF630e" found in 4 different chains.
Rinkeby, Kovan, Ropsten, BscScan. Looks like your metamask is connected to Kovan but contract is not deployed to Kovav. Verify which chain your contract is connected and connect to that network in Metamask
Once check the contract is selected correct, If you select AggregationV3Interface contract and deploy it throws this error, select the sol file you are working on and try XD

Solidity: TypeError: Function declared as view, but this expression modifies the state and thus requires non-payable (the default) or payable

I have been trying to create a smart contract/Token, will deploy this on the Binance Smart Chain test net. I followed some documentation and started with this. I am getting into this function issue. Function is declared as Read only. Here is the source code
The function is changing the state of the Owner Address, what is the other option to declare it as read only
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.2;
//import "Context.sol";
//import "IBEP20.sol";
//import "SafeMath.sol";
//import "Ownable.sol";
contract SampleTaken {
mapping(address => uint) public balances;
uint public totalSupply = 1000000 * 10 ** 18;
string public name ="Sample Token";
string public symbol ="KJA";
uint public decimals = 18;
/** Events aailable for the Contract**/
event Transfer(address indexed _from, address indexed _to, uint256 _value);
constructor(){
balances[msg.sender] = totalSupply;
}
function balanceOf(address _ownerAddress) public view returns (uint){
return balances[_ownerAddress];
}
function transfer(address _toAddress, uint _noOfTokens) public view returns (bool){
require(balanceOf(msg.sender) >= _noOfTokens, "Total balance is less than the number of Tokens asked for !!!");
balances[_toAddress] +=_noOfTokens;
balances[msg.sender] -= _noOfTokens;
emit Transfer(msg.sender,_toAddress, _noOfTokens);
return true;
}
function transferFrom(address _from, address _to, uint _value) public returns (bool){
require(balanceOf(_from) >= _value, "Balance is less than the number of Tokens asked for !!!");
// require(allowance[_from][msg.sender] >= _value, "Allowance too low");
balances[_to] += _value;
balances[_from] -= _value;
emit Transfer (_from, _to, _value);
return true;
}
}
Any help is much appreciated.
Regards
Your transfer() function is declared as a view function.
Functions can be declared view in which case they promise not to modify the state.
Source: Solidity docs
But these lines (within the transfer() function) modify the state:
balances[_toAddress] +=_noOfTokens;
balances[msg.sender] -= _noOfTokens;
emit Transfer(msg.sender,_toAddress, _noOfTokens);
If you want your function to modify the state, it cannot be a view (nor a pure) function - and you need to remove the view modifier:
function transfer(address _toAddress, uint _noOfTokens) public returns (bool){
Remove view or pure keyword from the function declaration and keep only public returns
Change
function transfer(address _toAddress, uint _noOfTokens) public view returns (bool)
to
function transfer(address _toAddress, uint _noOfTokens) public returns (bool)
Changed method:
function transfer(address _toAddress, uint _noOfTokens) public returns (bool){
require(balanceOf(msg.sender) >= _noOfTokens, "Total balance is less than the number of Tokens asked for !!!");
balances[_toAddress] +=_noOfTokens;
balances[msg.sender] -= _noOfTokens;
emit Transfer(msg.sender,_toAddress, _noOfTokens);
return true;
}

How Do I Add A checkBalance Function To This ERC20 Smart Contract

I Need To Know The Balance Of This Token After I Deploy It In Remix Ethereum Firefox. I Want To Know Where Do I Add The checkBalance Function. Plz Help Guys. This Is My First ERC20 Smart Contract.
pragma solidity ^0.5.0;
contract TusharCoin {
uint256 public totalSupply;
string public name;
string public symbol;
uint32 public decimals;
address public owner;
mapping(address => uint256 ) balances;
event Transfer(address to, uint256 amount);
constructor () public {
symbol = "TUSHAR";
name = "TusharCoin";
decimals = 5;
totalSupply = 100000000000;
owner = msg.sender;
balances[msg.sender] = totalSupply;
emit Transfer(msg.sender, totalSupply);
}
}
Your token currently isn't an ERC20 token as it doesn't fully implement the ERC20 standard yet.
To just add a balanceOf function to your existing contract you can add the following:
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
If you are creating your own ERC20 implementation then you should consider using SafeMath, see the documentation for details: https://docs.openzeppelin.com/contracts/2.x/utilities#math
If you are creating ERC20 tokens you may want to look at the OpenZeppelin Contracts implementation to see if this meets your needs. See the documentation for details: https://docs.openzeppelin.com/contracts/2.x/tokens#ERC20
An example ERC20 Token that you can deploy with Remix inheriting from the OpenZeppelin Contracts implementation is below using your specified name, symbol, decimals and totalSupply:
pragma solidity ^0.5.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.3.0/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.3.0/contracts/token/ERC20/ERC20Detailed.sol";
contract Token is ERC20, ERC20Detailed {
constructor () public ERC20Detailed("Tushar Token", "TUSHAR", 5) {
_mint(msg.sender, 1000000 * (10 ** uint256(decimals())));
}
}
If you have questions on using OpenZeppelin you can ask in the Community Forum: https://forum.openzeppelin.com/
Disclosure: I am the Community Manager at OpenZeppelin
Below, I have mention checkBalance function. In ERC20 standards checkBalance function to be stated as a balanceOf function.
In function, view means one can only read not write
function balanceOf(address accountAddress) public view returns (uint256) {
return balances[accountAddress];
}
Full source code.
pragma solidity ^0.5.0;
contract TusharCoin {
uint256 public totalSupply;
string public name;
string public symbol;
uint32 public decimals;
address public owner;
mapping(address => uint256 ) balances;
event Transfer(address to, uint256 amount);
constructor () public {
symbol = "TUSHAR";
name = "TusharCoin";
decimals = 5;
totalSupply = 100000000000;
owner = msg.sender;
balances[msg.sender] = totalSupply;
emit Transfer(msg.sender, totalSupply);
}
function balanceOf(address accountAddress) public view returns (uint256) {
return balances[accountAddress];
}
}
If you want whole code for ERC20. Let me know.

How to send ether from eoa to contract

I need to send ether from externally owned account to contract.
All code I found so far looks like this
contract Contract {
mapping (address => uint) balances;
event Transfer(address indexed _from, uint256 _value);
function deposit() public returns (uint) {
balances[msg.sender] += msg.value;
Transfer(msg.sender, msg.value);
return balances[msg.sender];
}
}
But I can not understand how does it work. I thought it should look like this: we should run some send function which will take current contract address, sender address and amount.
Can someone explain me the logic behind it?
I also found the solution which correspond to this logic
contract Contract {
function pay() payable {}
}
and than call it from console like that
var contract
Contract.deployed().then(function(instance) { contract = instance; })
contract.pay.sendTransaction({from: eoa_address,to: contract_address,value: web3.toWei(amount,"ether"), gas:1000000})
But in this case sendTransaction function called outside of contact.
Is there any way of calling it like from this perspective inside contract?
to send Ether to a contract :
we could create a payable function if we need to pay to execute this function
contract Contract {
function do_somthing() payable {
action1
action2
...
}
}
if we want to just send ethers to the contract without executing any function we define the fallback function as you presented in your question :
contract Contract {
function pay() payable {}
}
the example you have provided before :
contract Contract {
mapping (address => uint) balances;
event Transfer(address indexed _from, uint256 _value);
function deposit() public returns (uint) {
balances[msg.sender] += msg.value;
emit Transfer(msg.sender, msg.value);
return balances[msg.sender];
}
}
is recording the balances sent by the users to the contract (this function needs to be declared as payable for the recent compiler : function deposit() public payable returns)
function deposit() public payable returns (uint) {
balances[msg.sender] += msg.value;
emit Transfer(msg.sender, msg.value);
return balances[msg.sender];
}