I Need to Write a Smart Contract, In This Smart Contract User Can Send Token to Each Account in ERC-20 Network.
sender :0x5C2879Ec550e2F65D557b540B7DEAB3A6d478d62
recipient : 0xB643992c9fBcb1Cb06b6C9eb278b2ac35e6a2711
token Address : 0xa36085F69e2889c224210F603D836748e7dC0088
Kovan Testnet
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";
contract DexB is ERC20("KiaDex","DEX") {
function SendTokenFromAddress(address token,address sender,address recipient,uint256 amount)
external {
IERC20 token = IERC20(token);
token.allowance(sender,address(token));
token.approve(sender,amount);
require(token.balanceOf(sender) >=amount , "your balance is low" ) ;
token.transferFrom(sender,recipient, amount);
}
}
when i want to send token from this address 0x5C2879Ec550e2F65D557b540B7DEAB3A6d478d62 to this address 0xB643992c9fBcb1Cb06b6C9eb278b2ac35e6a2711 it dose not work and show me this message and afte that show not success transaction :
**whats the problem ? how can i sene Token from User Address to User Address in solidity ? **
The sender, which in your case is 0x5C2879Ec550e2F65D557b540B7DEAB3A6d478d62 needs to approve the wallet address that's calling the sendTokenFromAddress function. The contract cannot do that on behalf of the account that needs to send tokens.
Related
Assuming I have a wallet, I want to authorize another wallet to send a transfer on my behalf, how do I implement the above using the following practice.
pragma solidity ^0.8.0;
import 'Token.sol';
contract TransferToken{
function transferFrom(address recipient, uint amount) external {
Token token = Token(0xd9145CCE52D386f254917e481eB44e9943F3555);
token.transferFrom(msg.sender, recipient, amount);
}
}
contract Owner {
function transfer(address recipient, uint amount) external {
Token token = Token(0xd9145CCE52D386f254917e481eB44e9943F39138);
token.approve(0x617F2E2fD72FD9D5503197092aC168c91465E7f2, amount);
TransferToken transferToken = TransferToken(0x617F2E2fD72FD9D5503197092aC168c91465E7f2);
transferToken.transferFrom(recipient, amount);}}
in the above example, i am using the openZappelin implementation for ERC20 on the import (Token.sol)
now my question is this ... since I want to use a real wallet with ERC20 token how do I implement the above example, I am thinking for this I don't need the import anymore, but I don't know how to implement it without too many mistakes already, I very new to solidity and I am using remix for the above implementation
will be glad if i could get a help on this
While attempting to fund me contract is tell me it encountered an error without specifying the error. I attempted to fund 0.1 eth through the fund function, and in the terminal it says:
[block:8404521 txIndex:12]
from: 0x8a9...e4303
to: FundMe.fund() 0x542...E109C
value: 100000000000000000 wei
data: 0xb60...d4288
logs: 0
hash: 0x29a...97939
and in the etherscan it says:status fail :
Contract 0x5422f3458be343e378e7a399e16fff548e7e109c
Warning! Error encountered during contract execution [execution reverted]
I tried looking for problems with my code and found none.
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.6 <0.9.0;
import "#chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
//import "#chainlink/contracts/src/v0.8/vendor/SafeMathChainlink.sol"; won't need in later complier versions.
contract FundMe {
mapping(address => uint256) public addressToAmountFunded;
function fund() public payable {
uint256 minimumUSD = 50 * 10 ** 18;
require( getConversionRate(msg.value) >= minimumUSD,"You need to send more Eth");
addressToAmountFunded[msg.sender] += msg.value;
}
function getVersion() public view returns (uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
return priceFeed.version();
}
function getPrice() public view returns (uint256){
AggregatorV3Interface priceFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
(,int256 answer,,,)=priceFeed.latestRoundData();
return uint256(answer * 10000000000);
}
//10000000000 = Gwei which is why we added 10 zeros to getPrice(answer) to convert it to Wei amount
function getConversionRate(uint256 ethAmount) public view returns (uint256){
uint256 ethPrice = getPrice();
uint256 ethAmountInUsd = (ethPrice * ethAmount)/ 1000000000000000000; //divide 2x because we added 10*((getPrice)answer))
return ethAmountInUsd;
}
}
Aggregator contract address "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419" belongs to mainnet
From here get the ETH/USD goerli testnet address:"0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e"
Now in order to call chainlink oracle you have to have LINK token in your contract. Get some link token to your conract address from the faucet
Import the token in metamask. you will see the amount
send link token from your metamask to your contract
deploy your contract. if you are using Remix IDE chose the injected provider to connect to metamask. Because chainlink contract is on goerli, so you need to be on Goerli testnet. Once deployment goes through you can call the fund function.
Since the fund function has no argument, you need to send the value alongside the transaction. That is why inside the function you have msg.value to access to the sent amount.
In Remix ide, under "GAS LIMITinput there isVALUEinput. you need to pass the amount in there before you call thefund` function.
I want to transfer some ether form my address to the smart contract, I have tried the code below but it doesn't work. How to transfer ether through msg.sender?
pragma solidity >=0.7.0 <0.9.0;
contract Test {
function testTransfer() external payable {
bool sent = payable(address(this)).send(msg.value);
require(sent, "invalid balance");
}
}
Once I trigger the function with the value of 1 ether, the error output is as below:
I'm sure that I have enough Ether in my address. What should I do to transfer the Ether? Thanks!
The transaction fails because the smart contract is trying to transfer the ether to himself, and the smart contract doesn't have defined the receive function so it can receive ether that way, for your example you could simply remove all the code inside the function and make another function to check the contract balance and it will work
pragma solidity >=0.7.0 <0.9.0;
contract Test {
function testTransfer() external payable {}
function getBalance() external view returns (uint256) {
return address(this).balance;
}
}
I'm trying to transfer an ERC721 token, but I'm getting the error ERC721: transfer caller is not owner nor approved for the transferToken method.
Main.sol
import "./ERC721.sol";
import "./Counters.sol";
contract Main is ERC721 {
using Counters for Counters.Counter;
Counters.Counter internal _tokenIds;
address payable internal admin;
constructor() ERC721("MyToken", "TOKEN") {
admin = payable(msg.sender);
}
}
Auction.sol
import "./Main.sol";
contract Auction is Main {
struct AuctionInfo {
uint256 tokenId;
address highestBidder;
uint highestBid;
}
mapping(string => AuctionInfo) private _auctionInfo;
function createAuction(string memory id) public {
_tokenIds.increment();
uint256 newTokenId = _tokenIds.current();
_mint(msg.sender, newTokenId);
_auctionInfo[id].tokenId = newTokenId;
}
function transferToken(string memory id) public {
require(msg.sender == _auctionInfo[id].highestBidder, "You are not the highest bidder");
safeTransferFrom(address(this), _auctionInfo[id].highestBidder, _auctionInfo[id].tokenId);
}
// other methods...
}
The minting contract is this and the owner of the token is the msg.sender of the minting method if I'm not mistaken. Am I to use the approve (or setApprovalForAll) for this each time before transferring? I've tried this, payable(this), and address(this) for the safeTransferFrom method, but none seem to be working.
For example, I tried the following, but get the same revert message:
approve(address(this), _auctionInfo[id].tokenId);
this.safeTransferFrom(address(this), _auctionInfo[id].highestBidder, _auctionInfo[id].tokenId);
The main principle behind any Blockchain is that nobody on the blockchain network should be trusted, and still the transactions should happen fool proof, with no possibility of any cheating being done (barring of course of some hacking).
If you invoke the approve method from the Auction contract, then the msg.sender for the approve function in the ERC721 token contract is your auction contract address. So, in other words, your Auction Contract is trying to approve itself to sell someone else's NFTs, which is not very trustworthy.
What should really happen is that owner of the NFT should invoke the approve method of the ERC721 contract - i.e. the transaction that you send for the approve function call, should be signed by the NFT owner wallet address. This way, the msg.sender for the approve function in the ERC721 contract will be the owner of the NFT. As per the ERC721 standards, the owner of the NFT can approve anyone they want, to sell their NFT(s), as the no-trust in the network is still maintained (At least I should be able to trust myself). The approve method should be invoked from within your DAPP, before the transferToken function is invoked from the DAPP.
Hope that explains why you are unable to transfer your ERC721 tokens.
Because of the internal visibility of the ERC721._approve() function, you can effectively perform the approval for the user.
Then you'll be able to execute the safeTransferFrom(tokenOwner, receiver, tokenId) from your contract, because your contract address is approved to operate this specific token even though it belongs to the tokenOwner.
This snippet mints the token, assigning the ownership to the msg.sender. But then it also calls the _approve() function that doesn't contain any validations and simply assigns the approval of the token to the Auction address.
pragma solidity ^0.8;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
contract Auction is ERC721 {
constructor() ERC721("CollectionName", "Symbol") {}
function createAuction() public {
uint256 newTokenId = 1;
_mint(msg.sender, newTokenId);
_approve(address(this), newTokenId);
}
}
You can see from the screenshot that the owner is 0x5B... (the user address) and that the token is approved for 0xd9... (the contract address).
Note: The _approve() function is internal - it can be called from the ERC721 contract and contracts deriving from it (in your case Main and Auction), but it can't be called from external contracts or end user addresses.
I have created a basic ERC20 token by implementing OpenZeppelin as follow in ERC20.sol file:
pragma solidity ^0.6.4;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC20/ERC20.sol";
contract Token is ERC20 {
constructor(string memory _name, string memory _symbol)
public
ERC20(_name, _symbol)
{
_mint(msg.sender, 10000000000000000000000000000);
}
}
Then implement another contract Contract.sol as follow:
import "./ERC20.sol";
pragma solidity ^0.6.4;
contract SimpleBank{
Token tokenContract;
constructor(Token _tokenContract) public {
tokenContract = _tokenContract;
}
function deposit(uint amt) public returns (bool) {
require(amt != 0 , "deposit amount cannot be zero");
tokenContract.transfer(address(this),amt);
return true;
}
}
As, I have deployed both contract from the address 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2 so, it holds 10000000000000000000000000000 tokens.
But when I call deposit function from same address I got the following error:
transact to SimpleBank.deposit errored: VM error: revert. revert The
transaction has been reverted to the initial state. Reason provided by
the contract: "ERC20: transfer amount exceeds balance". Debug the
transaction to get more information.
So, what is the proper way to interact with the deployed ERC20 token so that the deploy function works.
The user address 0xAb8483... sends a transaction executing SimpleBank's function deposit(), which makes 0xAb8483... the value of msg.sender in SimpleBank.
But then SimpleBank sends an internal transaction executing Token's function transfer(). Which makes SimpleBank address (not the 0xAb8483...) the value of msg.sender in Token.
So the snippet tokenContract.transfer(address(this),amt); within SimpleBank is trying to send SimpleBank's tokens. Not the user's (0xAb8483...) tokens.
This transfer of tokens (from point 2) reverts, because SimpleBank doesn't own any tokens. Which makes the top-level transaction (from point 1) revert as well.
If you want SimpleBank to be able to transfer 0xAb8483...'s tokens, 0xAb8483... needs to approve() the tokens first to be spent by SimpleBank. Directly from their address, so that they are msg.sender in the Token contract.
Only then SimpleBank can execute transferFrom(0xAb8483..., address(this), amt) (from, to, amount).
TLDR: Your contract can't spend tokens that it doesn't own, unless the owner has manually approved your contract to spend them.
If it could spend someone else's tokens without approval, it would be very easy to steal from people who can't/don't verify your source code (by spending their USDT, WETH and other widely-used tokens).