How can I automatically convert all incoming coins and tokens to BUSD? - ethereum

e.g; With the receive() function in the BEP20 network, I capture when a money is transferred and trade with a script. But when other tokens such as WBNB, USDT are sent, I cannot do anything.
What I want to do: convert all coins and tokens directly transferred to the contract to busd via receive or fallback (or whichever works with) pancakeswap and mapping(address => uint) balance; I want to import the MAP into it.
I searched a lot but couldn't find the result I was looking for.
Could you please share which is the required source code for this process?
I using this function:
contract SendMoney{
mapping(address => uint) balance;
receive() external payable {
SendedMoney(msg.sender, msg.value);
}
function SendedMoney(address _senderaddress, uint _amount){
balance[_senderaddress] = _amount;
}
}

Those are BEP20 Tokens they don't have a receive() function.
This means the smart contract doesn't know that somebody sent you those tokens.
You would have to implement some off-chain bot that would track if your contract got any tokens and then call some swap() function.

Related

Solidity smart contract audit

I have a solidity code to audit like this
pragma solidity ^0.8.0;
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
// Allow to split the balance through complex rules
interface Split{
function getAddressAndAmountToSplit() view external returns(address, uint);
}
// MyBank contract
// This contract allows anyone to store any ERC20 tokens
contract MyBank {
// (token => user => amount)
mapping (address => mapping(address => uint)) public userBalance;
// (address => Split contract)
mapping (address => Split) splits;
// Deposit ERC20 tokens to the contracts
// The user must approve the bank before calling addToBalance
function addToBalance(IERC20 token, uint amount) external {
token.transferFrom(msg.sender, address(this), amount);
userBalance[address(token)][msg.sender] += amount;
}
// Withdraw part of the balance
function withdrawBalance(IERC20 token) external {
token.transfer(msg.sender, userBalance[address(token)][msg.sender]);
userBalance[address(token)][msg.sender] = 0;
}
// Allow to register a split contract
function registerSplit(Split split) external {
splits[msg.sender] = split;
}
// Split the balance into two accounts
// The usage of a Split contract allows to create complex split strategies
function splitBalance(IERC20 token) external {
Split split = splits[msg.sender];
require(split != Split(address(0x0)));
uint balance = userBalance[address(token)][msg.sender];
(address dest, uint amount) = Split(split).getAddressAndAmountToSplit();
userBalance[address(token)][dest] = amount;
userBalance[address(token)][msg.sender] = balance - amount;
}
}
What I found.
function withdrawBalance(IERC20 token) external possible reentrancy attack, because we check balance in the end
function splitBalance(IERC20 token) external - vulnerable business logic, because if amount is greater than balance we get negative value and possible integer overflow
If you have any idea of possible vulnerabilities of code above, please feel free to provide any further assistance
Probably a bit late but if anyone reads this for why I think these aren’t vulnerabilities. First of all, there are no reentrancy attacks possible here, due to the fact that transfer function only forwards 2300 gas, which is quite not enough to execute something meaningful.
Secondly, its possible to add a require check if balance is bigger than the amount. But since contract is using later than or equal to 0.8.0 compiler versions, if amount is indeed bigger than balance, it will automatically revert due to underflow.
I think as a smart contract auditor, you should know these better.

How to transfer an ERC721 token

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.

Why can't I use this transferEther function to send Ether to the smart contract?

I have this code I have entered into Remix IDE, as ReceivedEther.sol, a standalone smart contract.
I've transferred 0.02 Ether to the smart contract, using MetaMask.
When I checked the smart contract's balance, it returns 200000000000000000, as expected.
If I try to use the transferEther function, however, and enter a number smaller than this - say, 0.005 ETH, or 50000000000000000 as the amount - it doesn't work using MetaMask.
When MetaMask prompts me it's never for that amount. It's for 0 ETH and 0.00322 gas fee (or whatever the gas is). Basically it always set the amount of ETH at 0 and only charges the fee.
Why can't I transfer an amount of ETH using this function in the Remix IDE with MetaMask?
pragma solidity ^0.8.0;
contract ReceivedEther {
function transferEther(address payable _recipient, uint _amount) external returns (bool) {
require(address(this).balance >= _amount, 'Not enough Ether in contract!');
_recipient.transfer(_amount);
return true;
}
/**
* #return contract balance
*/
function contractBalance() external view returns (uint) {
return address(this).balance;
}
}
Your code sends ETH (stated in the _amount variable) from the smart contract to the _recipient. So it doesn't require any ETH to be sent in order to execute the transferEther() function.
If you want your contract to accept ETH, the function that accepts it (or the general fallback() or receive() function) needs to be marked as payable.
Example:
pragma solidity ^0.8.0;
contract ReceivedEther {
receive() external payable {} // note the `payable` keyword
// rest of your implementation
}
Then you can send whathever amount of ETH to the smart contract address (without specifying any function to execute).
See more at https://docs.soliditylang.org/en/v0.8.5/contracts.html#receive-ether-function
If you want to prefill the amount in MetaMask from Remix IDE, you can use the "Value" input in the "Deploy & Run Transactions" tab.

How to interact with the deployed ERC20 token with another smart-contract?

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).

How ERC20 tokens control access to their functions?

Here is my question (basically, I want to know if I am right or mistaken):
First of all, we have standard ERC20:
contract ERC20Interface
{
function transfer(address _to, uint _value) public returns (bool success);
function transferFrom(address _from, address _to, uint _value) public returns (bool success);
function approve(address _spender, uint _value) public returns (bool success);
.....
}
Then, in a CrowdSale, we have a token, derived from it:
contract ICO is Ownable {
...
MyToken public m_token;
...
function ICO() public {
m_token = new MyToken();
...
Then the crowdsale ends. The token with list of all people (addresses) that bought it becomes "free" of crowd sale contract:
function finish() onlyOwner public {
if(goalReached()) {
m_token.transferOwnership(m_addrOwner);
My questions:
1. For this token to be traded on exchanges, I have to somehow provide these exchanges with token's address. Where should I get it?
2. Am I correct? Is it how it supposed to work?
In other words, if a token is a separate contract, passed to ICO contract by address, I can see how exchanges can trade it after the end of crowd sale: they have that same address.
But I see a lot of crowdsales on Etherscan, that create contract internally (like in code snippets above). How do I make it "tradable" after the end of a crowd sale in this case?
Thanks.
Most exchanges will only support your token if they see value in it. You'd have to contact the exchanges and they will evaluate if it's worth it to them based on the demand for your token. Even then, they will most likely ask for payment up front before listing.
For example, Bittrex has their submission process documented here. They offer free listing once you pass their verification process (along with some non-free services). Other exchanges follow a similar process.
The contract address you're looking for that you'd have to provide is returned to your client when you deploy your token contract. If you somehow lose the address in your client, you can find it on etherscan.io by searching for the token name/symbol (assuming your token contract follows the ERC20 spec) or by transaction hash. You can also retrieve the address in code:
function getTokenAddress() constant returns (address) {
return address(m_token);
}
Outside of an exchange, you can also do private transfers of tokens by simply adding the token contract address to a wallet like Mist or Parity and sending tokens between addresses.
Note that all of this is independent of the crowd sale. The crowd sale is a separate contract that is used to raise money and do the initial token distribution.