Please pardon me if this question sounds dumb, but I am a little new to this concept and there are not many resources out there I could find. Thanks.
Suppose I have created a ERC721 smart contract and used that to mint an NFT token. Now I want to be able to transfer that token from one network to another. I know to mint transfer the NFT to another user, the owner needs to approve the transaction. I have already tried this on rinkeby testnet. But I have no idea how to transfer from say rinkeby testnet to another network. Please see my mint and transfer functions below:
function _transfer(
address _from,
address _to,
uint256 _tokenId
) external payable {
require(ownerOf(_tokenId) == _from);
_owners[_tokenId] = _to;
_balances[_from]--;
_balances[_to]++;
emit Transfer(_from, _to, _tokenId);
}
function _mint(address _to, uint256 _tokenId)
internal
uniqueToken(_tokenId)
notZeroAddress(_to)
{
_owners[_tokenId] = _to;
_balances[_to] += 1;
tokenExist[_tokenId] = true;
emit Transfer(address(0), msg.sender, _tokenId);
}
I would appreciate any assistance. Thanks.
Cross chain (network) transactions need a bridge. It can be a centralized one or it can be trust-less and decentralized one like near rainbow bridge.
It's not a trivial problem to tackle.
Following links might give you insight on how it should get done.
near rainbow bridge
avalanche bridge
cosmos IBC
polkadot bridges
Related
i had a small question that i creast a contract A and there is 1 busd token in the contract A, now i want to transfer the 1 busd out of contract by owner address
how to set the contractA?
i have use this code to deploy and test
pragma solidity ^0.8;
interface IERC20 {
function transfer(address to, uint256 amount) external returns (bool);
}
contract MyContract {
address owner = 0xFAD69bCefb704c1803A9Bf8f04BC314E78838F88;
function withdrawToken(address tokenContract, uint256 amount) external {
// send `amount` of tokens
// from the balance of this contract
// to the `owner` address
IERC20(tokenContract).transfer(owner, amount);
}
}
the feedback is
This contract may be abstract, it may not implement an abstract parent's methods completely or it may not invoke an inherited contract's constructor correctly.
can someone help me? thanks in advance , i am beginner.
find a way to transfer the busd out of contract .
I recognize this code from my other answer. :)
You're trying to deploy the IERC20 interface - which throws the "This contract may be abstract" error.
You need to deploy the other contract. Depending on how you deploy the contract, there are different ways to do that.
Here's another answer that shows how to select the desired contract in Remix IDE. However, note that this code won't work on the Remix emulated network, as the BUSD contract is not available there. You'll need to deploy the code either to the mainnet or your local fork of the mainnet, where the BUSD contract is available.
I'm trying to understand what this lines of BEP20 code mean, it is written in solidity
constructor () {
_rOwned[owner()] = _rTotal;
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
uniswapV2Router = _uniswapV2Router;
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[address(this)] = true;
emit Transfer(address(0), owner(), _tTotal);
In the first lines, he instanciate UniswapV2Router pointing the address router to PancakeSwap. This because, he want to create a liquidity pool with his TOKEN and BNB, indeed after this instanciating operation he call createPair() that allows him to create this pair between his smart contract and the address WETH().
IMPORTANT: WETH() is a function that provider the chain native wrapped coin address where smart contract was deployed. For example: If I create a pair instanciating Uniswap router on Ethereum blockchain then WETH() will return address about WETH (Wrapping Ether) address present into Etheruem. On the contrary if I instanciate Uniswap Router with its address present into binance smart chain (and so I refers to Pancakeswap in this case), the value of WETH() will be WBNB address.
After this lines of code, I assume that he excluded from paying a fee for only transactions the owner() address (who deployed the smart contract for the first time) and smart contract itself.
Finally he emitted a Transfer event passing : address(0) (0x0000000000000000000000000000000000000000), owner() and total supply.
More information about pair on documentation.
I have 2 Contracts. One is an ERC721 Token (NFTCollectables). The other one is a market including an auction system (NFTMarket).
An auction can be claimed after it ended and only by the highest bidder.
When claiming an auction the transfer method of the NFTCollectables contract is called to transfer the NFT from the markets address to the address of the highest bidder.
I do not exactly understand why the exception comes, but it occurs at/inside the transfer method of the NFTCollectables contract. The strange thing is that even the last line of code inside the transfer method is getting executed (tested by putting a require(false, 'test') after _transfer(msg.sender, to, nftId)). But nothing after ctr.transfer(auction.highestBid.bidder, auction.nftId) is getting executed (tested by putting a require(false, 'test') after it).
Could it have to do with the gas limit?
Any idea is appreciated, thanks!
NFTMarket
function claimAuction(uint auctionIndex) external {
require(auctionIndex < auctions.length, "no auction");
Auction memory auction = auctions[auctionIndex];
require(block.timestamp <= auction.end, "auction still active");
NFTCollectables ctr = NFTCollectables(nftCollectablesAddress);
ctr.transfer(auction.highestBid.bidder, auction.nftId);
// deleting auction from active auctions list
for (uint i; i < activeAuctionIndexes.length; i++) {
if (activeAuctionIndexes[i] == auctionIndex) {
delete activeAuctionIndexes[i];
break;
}
}
emit AuctionEnd(auction.highestBid.bidder, auction.highestBid.price, auction.nftId);
}
NFTCollectables
function transfer(address payable to, uint nftId) external payable {
require(_exists(nftId), "transfer of non existing token");
require(_isApprovedOrOwner(msg.sender, nftId), "Sender not approved nor owner");
_transfer(msg.sender, to, nftId);
}
If you have deployed the contracts on the public network, like mainnet or testnet, use https://tenderly.co or EtherScan to debug the revert reason.
If you are running the contracts using unit tests then keep modifying the contracts e.g. by removing lines to see when it starts failing. Or alternatively use a better smart contract development framework like Brownie which will give you the cause of revert right away.
We had implemented a function on our codebase that i can share with you. This function is used to transfer ownership of nft to who wins the auction.
function transferNFTtoNewOwner(NFTItem memory t,address oldOwner, address newOwner) internal {
require(newOwner != address(0), "New owner can't be address zero.");
XXXX storage r = creatureList[t.tokenAddress][t.tokenId];
IERC721 nft = IERC721(t.tokenAddress);
nft.safeTransferFrom(oldOwner, newOwner, t.tokenId);
address currOwner = nft.ownerOf(t.tokenId);
require(newOwner == currOwner, "Problem on nft transfer");
r.owner = newOwner;
}
The major differences are we used safetransferfrom here. If your contract owns the NFT then you can call safeTransfer. and after that we checked the nft owner with require statement. If you put this statement and change your transfer function to safetransfer and the transaction still revert without giving any error on etherscan then you can investigate about your nft contract.
Can anyone help me?
I created a basic contract.But don't know the withdrawal function.Please help me.Thanks everyone
I tried creating a basic function but it doesn't work
function withdraw() public {
msg.sender.transfer(address(this).balance);
}
payable(msg.sender).transfer(address(this).balance);
This line withdraws the native balance (ETH if your contract is on Ethereum network).
To withdraw a token balance, you need to execute the transfer() function on the token contract. So in order to withdraw all tokens, you need to execute the transfer() function on all token contracts.
You can create a function that withdraws any ERC-20 token based on the token contract address that you pass as an input.
pragma solidity ^0.8;
interface IERC20 {
function transfer(address _to, uint256 _amount) external returns (bool);
}
contract MyContract {
function withdrawToken(address _tokenContract, uint256 _amount) external {
IERC20 tokenContract = IERC20(_tokenContract);
// transfer the token from address of this contract
// to address of the user (executing the withdrawToken() function)
tokenContract.transfer(msg.sender, _amount);
}
}
Mind that this code is unsafe - anyone can execute the withdrawToken() funciton. If you want to run it in production, add some form of authentication, for example the Ownable pattern.
Unfortunately, because of how token standards (and the Ethereum network in general) are designed, there's no easy way to transfer "all tokens at once", because there's no easy way to get the "non-zero token balance of an address". What you see in the blockchain explorers (e.g. that an address holds tokens X, Y, and Z) is a result of an aggregation that is not possible to perform on-chain.
Assuming your contract is ERC20, The transfer function defined in EIP 20 says:
Transfers _value amount of tokens to address _to, and MUST fire the
Transfer event. The function SHOULD throw if the message caller’s
account balance does not have enough tokens to spend.
Note Transfers of 0 values MUST be treated as normal transfers and
fire the Transfer event.
function transfer(address _to, uint256 _value) public returns (bool
success)
When you're calling an implementation of transfer, you're basically updating the balances of the caller and the recipient. Their balances usually are kept in a mapping/lookup table data structure.
See ConsenSys's implementation of transfer.
I came here to find a solution to allow the owner to withdraw any token which accidentally can be sent to the address of my smart contract. I believe it can be useful for others:
/**
* #dev transfer the token from the address of this contract
* to address of the owner
*/
function withdrawToken(address _tokenContract, uint256 _amount) external onlyOwner {
IERC20 tokenContract = IERC20(_tokenContract);
// needs to execute `approve()` on the token contract to allow itself the transfer
tokenContract.approve(address(this), _amount);
tokenContract.transferFrom(address(this), owner(), _amount);
}
Since it is a basic contract, I assume it is not erc20 token and if you just want to withdraw money:
function withdraw(uint amount) external onlyOwner{
(bool success,)=owner.call{value:amount}("");
require(success, "Transfer failed!");
}
This function should be only called by the owner.
If you want to withdraw entire balance during emergency situation:
function emergencyWithdrawAll() external onlyWhenStopped onlyOwner {
(bool success,)=owner.call{value:address(this).balance}("");
require(success,"Transfer failed!");
}
this function have two modifier: onlyWhenStopped onlyOwner
Use the Emergency Stop pattern when
you want to have the ability to pause your contract.
you want to guard critical functionality against the abuse of undiscovered bugs.
you want to prepare your contract for potential failures.
Modifiers:
modifier onlyOwner() {
// owner is storage variable is set during constructor
if (msg.sender != owner) {
revert OnlyOwner();
}
_;
}
for onlyWhenStopped we set a state variable:
bool public isStopped=false;
then the modifier
modifier onlyWhenStopped{
require(isStopped);
_;
}
I have a erc20 token and in another contract I want to create a token swap function.
So very easily, one send a usdc token and swap my erc20 token in 1:1 ratio.
Problem is how to approve to spend my erc20 token. I tried several times but can't find a way.
interface IERC20 {...}
contract AnotherContract {
function approve(address _spender, uint256 _amount) public returns(bool) {
return IERC20(MyToken).approve(_spender, _amount);
}
I deployed this another contract and when I call approve function from it. So When I set '_spender' to this contract address. The result is weird. So this contract is owner and spender both.. As I think a user should be as a owner and this contract should be a spender. But function calling from onchain. the msg.sender is going to be this contract address self.
I don't understand and am confusing. anybody knows or have some rescoures? Thank you.
When your AnotherContract executes the approve() function in MyToken, the msg.sender in MyToken is AnotherContract - not the original transaction sender.
Which effectively approves AnotherContract's tokens to be spent by _spender.
Unless the MyToken has a way to delegate the approval (e.g. by using a deprecated tx.origin instead of msg.sender, which introdues a security flaw), the user will have to execute the approval manually, and not through your external contract.
Many ERC-20 implementations use this approach for security purposes. For example to prevent a situation, where a scammer would persuade a user to execute their malicious function, because the user would think they are getting an airdrop.
// function name suggests that the caller is going to receive an airdrop
function claimAirdrop() external {
/*
* fortunately, this won't work
* and the tx sender can't approve the scammer to spend their tokens this way
*/
USDTcontract.approve(scammer, 1000000);
}