Remove unstrusted token from ERC20 Smart Contract - solidity

I have a question and I try to google without much existence.
Let's take the example of this token:
1inch Token
So you can see that it has different tokens that people have sent to that address.
If I were the owner, how could I implement a function to withdraw all those tokens to my wallet?

Your contract can define the ERC20 interface function transfer(), and then execute this function on the external token contract.
pragma solidity ^0.8;
interface IERC20 {
function transfer(address _to, uint256 _amount) external returns (bool);
}
contract MyContract {
modifier onlyOwner {
require(msg.sender == address(0x123), 'Not authorized');
_;
}
function withdrawERC20Token(address _tokenContractAddress, uint256 _amount) external onlyOwner {
IERC20 token = IERC20(_tokenContractAddress);
// transfer the `_amount` of tokens (mind the decimals) from this contract address
// to the `msg.sender` - the caller of the `withdrawERC20Token()` function
bool success = token.transfer(msg.sender, _amount);
require(success, 'Could not withdraw');
}
}

Related

Problem sending eth from contract to contract

pragma solidity ^0.8.7;
// SPDX-License-Identifier: MIT
contract Client {
address payable private hub;
address payable public owner;
uint256 public balance;
constructor(address payable _hub) {
hub = _hub;
owner = payable(msg.sender);
}
receive() payable external {
balance += msg.value;
}
function withdraw(address payable destAddr) public {
require(msg.sender == owner, "Only owner can withdraw funds");
uint amount = address(this).balance;
destAddr.transfer(amount);
}
function start() public payable {
require(msg.sender == owner, "Only owner can start the process");
uint amount = address(this).balance;
hub.transfer(amount);
balance = 0;
}
function setHub(address payable _new) public {
require(msg.sender == owner, "Only owner can change address");
hub = _new;
}
}
Hi i have a problem, when I deploy this contract and put as input (hub) the other contract, then send eth to this contract, i call the "start" function and throw a gas estimation error.
Someone who can help me pls...
I'm expecting that calling the start function fund will be sent to the other contract that also have a function for receiving eth
receive() payable external {
balance += msg.value;
}
You are getting that gas estimation error because your receive function on the second contract is not empty and the transaction does not have enough gas to execute the code. transfer only sends the amount of gas necessary to execute a transfer of ether (21,000 gas) and nothing more.
You can use call instead of transfer to send ether and set the amount of gas that you want to send. transfer is actually no longer recommended for sending ether.

How do I accept an ERC20 token for Nft mint payment instead of ETH

How do I accept an ERC 20 token for minting NFTS on my smart contract. I’m currently paying for the minting using ETH, and I will like to accept another ERC 20 token.
You can change your mint function in order to accept the preferred token type as payment. And in order to prevent paying gas in eth, you can use biconomy forward.Check out their docs.
https://docs.biconomy.io/products/enable-paying-gas-in-erc20
You need a reference from the NFT contract to your token contract.
Let's say we have these two contracts: NFTContract, TokenContract.
contract NFTContract {
TokenContract tokenContract;
...
mint() {
tokensContract.transfer(msg.sender(), addressReceiver, tokensToSend);
...
}
}
contract TokenContract {
transfer(sender, receiver, balance) {}
}
You can check an example of how I did this in my repo I'm developing for my thesis.
https://github.com/NickVanzo/Contracts_For_Thesis
Maybe it will work for you but be careful you can take errors for solidity versions.
pragma solidity ^0.8.9;
import "#openzeppelin/contracts/token/ERC721/ERC721.sol";
import "#openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "#openzeppelin/contracts/token/ERC20/ERC20.sol";
contract LSTNFT is ERC721, ERC721Burnable, Ownable {
uint256 public cost;
uint256 maxSupply = 20;
uint256 maxMintAmountPerTx = 2;
// address of the ERC-20 contract
address public erc20Contract = "ERC-20 address is here";
// instance of the ERC-20 contract
ERC20 public erc20;
constructor() ERC721("Lestonz NFT", "LSTN") {
erc20 = ERC20(erc20Contract);
}
function _baseURI() internal pure override returns (string memory) {
return "ipfs://your ipfs url";
}
modifier mintPriceCompliance(uint256 _mintAmount) {
if (msg.sender != owner()) {
require(msg.value >= cost * _mintAmount, 'Insufficient funds!');
}
_;
}
function mint(uint256 _mintAmount) public payable mintPriceCompliance(_mintAmount) {
require(erc20.balanceOf(msg.sender) >= msg.value, "Not enough ERC-20 tokens");
_safeMint(_msgSender(), _mintAmount);
}
function setCost(uint256 _cost) public onlyOwner {
cost = _cost;
}
}

Why can't I transfer USDT to my smartcontract?

When I call transferUSDT i got a 'BEP20: transfer amount exceeds balance' but i know i got suffisent funds. I think i miss something in my smart contract.. Here the error on the bscscan:
https://testnet.bscscan.com/tx/0x3a253a8c32ed19bdbed66499ec2f888eae5114d44eba7c2f28a185258e91641f
pragma solidity >=0.7.0 <0.9.0;
abstract contract IUSDT{
function approve(address _spender, uint _value) virtual external returns (bool);
function transferFrom(address _from, address _to, uint _value) virtual public;
function transfer(address recipient, uint256 amount) virtual external returns (bool);
}
contract usdtTransfer{
IUSDT TetherContract;
function transferUSDT(uint256 amount) public {
TetherContract.transfer(address(this),amount);
}
constructor(address _tetherAddress){
TetherContract=IUSDT(_tetherAddress);
}
}
TetherContract.transfer(address(this),amount);
This snippet is trying to transfer amount (2nd argument) of tokens to the address(this) (1st argument) address - which is the address of the usdtTransfer contract.
And since it's executed from the usdtTransfer contract, it's trying to send the tokens from the very same usdtTransfer address.
If your goal is to send the tokens from the user to your contract, the user needs to first execute the approve() function on the token contract (from their address, passing your address as the spender param).

Transaction Reverted even though I have a payable fallback function to receive eth, when I deploy without sending eth it works

Here is my code:
pragma solidity 0.8.6;
import "./Allowance.sol";
contract SharedWallet is Allowance {
event MoneySent(address indexed _beneficiary, uint _amount);
event MoneyReceived(address indexed _from, uint _amount);
function withdrawMoney(address payable _to, uint _amount) public ownerOrAllowed(_amount) {
require(_amount <= address(this).balance, "Contract doesn't own enough money");
if(!isOwner()) {
reduceAllowance(msg.sender, _amount);
}
emit MoneySent(_to, _amount);
_to.transfer(_amount);
}
function renounceOwnership() public override onlyOwner {
revert("can't renounceOwnership here"); //not possible with this smart contract
}
fallback () external payable {
emit MoneyReceived(msg.sender, msg.value);
}
}
Are you trying to send Ether to the contract as you deploy it? As I do not think you can do that easily. Well, there is a hacky way. Ethereum contract address is deterministic, i.e. knowing the creator's address and their nonce you can calculate the future address of your smart contract. And then send ETH to that address prior to deploying the contract.

A Lottery Solidity Smart Contract Accept token as payment instead of ether

pragma solidity ^0.4.21;
contract Lottery {
address public manager;
address[] public players;
constructor() public {
manager = msg.sender;
}
function enter() public payable {
require(msg.value > .01 ether);
players.push(msg.sender);
}
function random() private view returns (uint) {
return uint(keccak256(abi.encodePacked(block.difficulty, now, players)));
}
function pickWinner() public restricted {
uint index = random() % players.length;
players[index].transfer(address(this).balance);
players = new address[](0);
}
function getPlayers() public view returns (address[]) {
return players;
}
modifier restricted() {
require(msg.sender == manager);
_;
}
}
I want o change the function
function enter() public payable {
require(msg.value > .01 ether);
players.push(msg.sender);
}
Instead of ether, user use our token/erc20 to enter the lottery
You can define an interface (in your contract) of the token contract. Since you're only going to be using the transferFrom() function, this is the only function that you need to define in the interface (no matter that the token contract contains other functions as well).
interface IERC20 {
function transferFrom(address _from, address _to, uint256 _amount) external returns (bool);
}
The you can execute the transferFrom() function of the token, passing it arguments:
from: the user executing your enter() function
to: your contract
amount: Assuming the token has 18 decimals (most tokens do), you can use the ether helper unit, because it effectively calculates "0.01 * 10^18 (or 10^16, or 10000000000000000) of the token smallest units", which is 0.01 of the token. Otherwise, you'll need to recalculate this number based on the token decimals.
function enter() public payable {
IERC20 token = IERC20(address(0x123)); // Insert the token contract address instead of `0x123`
require(token.transferFrom(msg.sender, address(this), .01 ether));
players.push(msg.sender);
}
Important: Mind that the user needs to approve() your contract to spend their tokens beforehand (from their address), otherwise the token transfer would fail. There's a security reason for that, read more about it in the bottom part of this answer.