How to create solidity function only callable by a wallet address (not a contract) - solidity

I want to make sure that my function isn't able to be called programmatically by another smart contract.
Is there a way to create a function in my contract that doesn't allow it to be called by other contracts while still allowing ordinary wallets to call the function?

So, msg.sender returns the address who called your method, and tx.origin returns the address of the account that sent the transaction.
/// #dev Check if method was called by user.
require(msg.sender == tx.origin, "Reverting, Method can only be called directly by user.");

Related

How to change old implementation contract address on etherscan?

I wrote upgradable smart contract using solidity and upgraded contract several time.
When I upgraded smart contract, implementation contract address was changed.
But under that address, the old implementation contract address still remains.
https://rinkeby.etherscan.io/address/0x245dBBE31f33569D3d7F1e0df10c93547c44065D#readProxyContract
How to change or hide this old address?
Particularly you can't hide anything once it is stored on the Blockchain. The old address will still be visible.
But if you want that calling to the old contract should fail, you can simply create a self destruct function inside your smart contract and call it when you have updated the smart contract and deployed it with a new address.
Tip -
Always have smart contracts with the self destruct functionality
Whenever you update your smart contract i.e deploy it to a new address, call the self destruct function on the old contract address for it to be destroyed.
Syntax for self destruct -
contract YourContract {
// State variables
// Some functions
function destruct(address addr) ownerOnly {
selfdestruct(addr);
}
// The above function sends all ether from the contract to the specified address
}

ERC721 Smart contract revoke approval

I've some question about ERC721 processing. I'd like to make an user to give aproval to an external smart contract for transfering one of its NFT.
To do it I'm using approve(to, tokenId).
Then, in some situation, the contract should be able to revoke its own autorisation by calling approve(address(0), tokenId)
(The NFT owner calls a cancel method from the smart contract that perform some operations and revokes its own permission on the token)
At this step, I got the following error:
ERC721: approve caller is not owner nor approved
My understanding is that in order to make the contract able to call approve, the NFT owner should have approved it with setApprovalForAll(operator, _approved)?
What about others NFT from the same collection owned by the user ? Would the contract be able to manage them too ?
I'd like to limit as much as possible the smart contract's permissions and stick to a very specific NFT transfer (with its token_id)
Can someone enlighten me on the right way to do it ?
It sounds like you have 2 contracts and an EOA involved in this process. You want the NFT contract to give another contract permission to transfer tokens, as well as remove that permission. You should be following this order:
1.) EOA calls approve(to, tokenID) on the NFT contract
2.) NFT contract has a function that calls approve(address(0), tokenID)
3.) Non-NFT contract calls the function in step 2
--> rever error
You would indeed get this error if Non-NFT contract has not been given approval permission for tokenID. Even though the token owner is calling that function, the context of the call reads the Non-NFT contract address as msg.sender. You could avoid this actually if the function inside the Non-NFT contract made a delegatecall instead of a regular call.
You do not need to use setApprovalForAll if you are only working with one NFT. You can give the contract approval by calling approve() and then revoke it with the method you stated above.

what is address of msg.sender when webjs proxy contract instance call logic contract abi?

In my test demo, I deployed a proxy at this proxy contract address, and I have a logic contract. When I used web3.js create a proxy contract at proxy contract with logic ABI, then call the logic contract function withdraw(address _recipient, address _tokenAddr, uint256 _amount) onlyWhitelisted public, what's the address of msg.sender in the called function of logic function? It's the user address or the address of proxy contract? In my logic contract, there is a public mapping(address => bool) whitelist. I want use whitelist[msg.sender] to check whether the original use address is in the whitelist. I have added my user address to the whitelist.But whitelist[msg.sender] always return false when via proxy contract to interactive with logic contract.
The proxy contract uses delegatecall() native function to redirect the request. Which also passes the original msg.sender.
what's the address of msg.sender in the called function of logic function
It's the original address that calls the proxy.
But whitelist[msg.sender] always return false when via proxy contract to interactive with logic contract.
When you're using a proxy contract, all storage values are stored on the proxy address - not on the logic address. So when you're querying value of whitelist[msg.sender], you need to use the ABI of the logic contract but the address of the proxy.

How much nfts can be transferd on 1 smart contract?

I can't figure out if i need to Deploy a smart contract for each transfer? or can 1 smart contract serve several transactions? Thanks ahead
You don't need to deploy another smart contract to transfer NFTs.
Info about each token ownership is stored in its collection contract. So you just need to execute the safeTransferFrom() function on the collection contract from the current owner address, passing it following params:
current owner (_from)
receiver (_to)
token ID (_tokenId)
There are several ways to execute the function from a regular (non-contract) address, for example using the UI of EtherScan/BSCScan under the Contract -> Write Contract section on the detail page of the collection contract address.
Note: All assuming the collection contract follows the ERC-721 standard.

How can I tell if a smart contract on RSK is an NFT?

Given an address of a smart contract deployed to RSK, how can I tell if it is an NFT or not? Is there a "standard" way to do this?
Yes there is a definitive way to do this,
if the smart contracts implement well-known token standards for NFTs,
which in turn implement the well-known EIP165 Standard Interface Definition.
(1) The easiest way to do this is to simply look up the address on the RSK block explorer.
If the smart contract address is 0x814eb350813c993df32044f862b800f91e0aaaf0, then go to
https://explorer.rsk.co/address/0x814eb350813c993df32044f862b800f91e0aaaf0
On this page, you will see a row for "Contract Interfaces",
and in the case of this smart contract,
displays ERC165 ERC721 ERC721Enumerable ERC721Metadata.
Since this contains ERC721, we know that it implements that token standard for non-fungible tokens.
(2) The more programmatic/ DIY way to do this is to use the function defined in the EIP165 standard, whose interface is copied below:
interface ERC165 {
/// #notice Query if a contract implements an interface
/// #param interfaceID The interface identifier, as specified in ERC-165
/// #dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// #return `true` if the contract implements `interfaceID` and
/// `interfaceID` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
Without going too much into the math of how this is calculated,
(read the EIP-165 standard for the full description/ explanation)
if invoking supportsInterface returns true, then you know
that that this smart contracts (claims to) implement that particular interface.
If you wish to test if a particular smart contract implements the
"Non-Fungible Token Standard":
call supportsInterface(0x80ac58cd)
If you wish to test if a particular smart contract implements the
"Multi Token Standard",
which is presently the 2nd most popular NFT standard:
call supportsInterface(0xd9b67a26)
(Note that while both of the above values are stated in their respective standards,
you may also wish to calculate them yourself, and the EIP-165 standard includes section on how to do this.)