I tried using interface to get owner address from another NFT smart contract (ERC721), what have I done wrong? - solidity

I tried using interface to get the owner address from another NFT smart contract (ERC721) like this:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface INft {
function owner() external view returns (address); //doesn't work
function name() external view returns (string calldata); //works
function ownerOf(uint256 tokenId) external view returns (address); //works
}
contract Test {
//doesn't work
function getNftProjectOwner (address _nft) external view returns (address){
return INft(_nft).owner();
}
//works
function getNftProjectName (address _nft) external view returns (string memory){
return INft(_nft).name();
}
//works
function getNftTokenOwner(address _nft, uint256 _tokenId) external view returns (address){
return INft(_nft).ownerOf(_tokenId);
}
}
So far all other external function call works except for the one that gets the nft smart contract owner address. Here's the reference from OpenZeppelin's Ownable.sol:
/**
* #dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
I also noticed that Ownable is an abstract contract and I'm wondering if I have declared it as an interface wrongly? I kept getting the error message "call to Test.getNftProjectOwner errored: execution reverted"

Related

How to access function of a contract instantiated with new?

I'm instantiating the contract called "Elector", applying new inside the function below, so far it works and the result is this one:
The contract is instantiated in memory with this address.
So, how do I access the getInformation() function inside this contract to use both in this main contract and in ethers in the dApp?
MAIN CONTRACT:
function updateConfirmedVotes(uint candidateId, VoteType electorVoteType) public {
_updateTotalElectoresVoted();
_pollingByCandidate[candidateId].votes.total += 1;
_pollingByCandidate[candidateId].votes.totalPercentage = _calculePercentageOfVote(_pollingByCandidate[candidateId].votes.total);
_pollingByCandidate[candidateId].electors.push(new _Elector({wallet: msg.sender, vote: electorVoteType}));
}
ELECTOR CONTRACT:
contract _Elector {
address private _wallet;
VoteType private _vote = VoteType.DID_NOT_VOTED;
constructor(address wallet, VoteType vote) {
_wallet = wallet;
_vote = vote;
}
function getInformation() external view returns (address, VoteType) {
return (_wallet, _vote);
}
}
Define a contract type variable within your Main contract, passing it pointer to the newly deployed Elector contract. Then you can invoke external/public functions defined by the contract type on the external address.
pragma solidity ^0.8;
contract Elector {
// ...
}
contract Main {
Elector elector;
function deployElector() external {
// returns pointer to the newly deployed contract
elector = new Elector();
}
function getInformationFromElector() external view returns (address, Elector.VoteType) {
// calls the external contract
return elector.getInformation();
}
}

Solidity - why does fallback() get called even though address.call{value:msg.value}("") does not have data?

The following contract calls another contract using an interface method (code to change):
pragma solidity 0.8.7;
interface MyStorage {
function setStorageValue(uint256) external;
}
contract StorageFactory {
uint256 storageValue;
constructor(uint256 _storageValue) {
storage = _storageValue;
}
function initStorage(MyStorage store) public payable {
store.setStorageValue(storageValue);
address payable storeAddress = payable(address(store));
storeAddress.call{value: msg.value}("");
}
}
Following is the StorageContract (code cannot be changed):
pragma solidity 0.8.7;
contract Storage {
int _storageValue;
function setStorageValue(int storageValue) public {
_storageValue = storageValue;
}
receive() external payable {
require(_storageValue == -1 || address(this).balance <= uint(_storageValue), "Invalid storage value");
}
fallback() external {
_storageValue = -1;
}
}
I use a test to call initStorage of the first contract by passing a Storage object, where the test is meant to fail because the value is set to a large amount. But somehow, the fallback() function seems to get called, setting the value to -1. I can't figure out why. Any help is appreciated.
Due to the solidity doc:
The fallback function is executed on a call to the contract if none of the other functions match the given function signature, or if no data was supplied at all and there is no receive Ether function. The fallback function always receives data, but in order to also receive Ether it must be marked payable.
Your function getting called because there's no overloading for the function
function setStorageValue(uint256 storageValue) public
So change the storageValue from int to uint256 will help.

is posible call public view return deployed, from anther contract?

Reading about the documentation.
https://docs.soliditylang.org/en/v0.5.3/units-and-global-variables.html#members-of-address-types
I have seen that one contract can call another, but they use gas.
It is possible to call a function like public view return
From another contract public view return?
The example would be something like that I have:
PointA
contract PointA {
uint256 number = 10;
function retrieve() public view returns (uint256) {
return number;
}
}
PointB
contract PointB {
address PointA = 0x9a6120275387Dc5Aa5dab0D87aeeee5894A3411B;
function retrieve() public view returns (uint256) {
uint256 PointA = PointA.call(bytes4(sha3("retrieve()")));
return PointA;
}
}
Only if the full chain of calls is (read-only) calls, not transactions.
PointA.sol
pragma solidity ^0.8;
contract PointA {
uint256 number = 10;
function retrieve() public view returns (uint256) {
return number;
}
}
PointB.sol
pragma solidity ^0.8;
interface PointA {
function retrieve() external view returns (uint256);
}
contract PointB {
PointA pointA = PointA(0xd9145CCE52D386f254917e481eB44e9943F39138);
function retrieve() public view returns (uint256) {
uint256 retrieved = pointA.retrieve();
return retrieved;
}
}
When you call (not transact to) PointB function retrieve(), it makes an EVM call to PointA function retrieve().
The naming of the call() function from your question is a bit unfortunate. It executes an EVM call (or sometimes called "message call", docs), but it's not related to the eth_call (read-only, gas-free) RPC method.

What is the type of `this` object in solidity

In the following claimPayment function that is used to claim a payment made earlier to this contract, the line bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this))); has this as part of the signed message. This makes me wonder what is this and what the type of this is. If I'm returning this in a function, what type is used for it? Thanks.
function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) public {
require(!usedNonces[nonce]);
usedNonces[nonce] = true;
// this recreates the message that was signed on the client
bytes32 message = prefixed(keccak256(abi.encodePacked(msg.sender, amount, nonce, this)));
require(recoverSigner(message, signature) == owner);
payable(msg.sender).transfer(amount);
}
this is a pointer to the current class instance, as in many other programming languages. You can for example point to public methods:
pragma solidity ^0.8.0;
contract MyContract {
function foo() external {
this.bar();
}
function bar() public {
}
}
When this is typecasted, it takes a form of the address, where the current instance is deployed.
pragma solidity ^0.8.0;
contract MyContract {
function foo() external view returns (bytes memory) {
return abi.encodePacked(this);
}
function bar() external view returns (address) {
return address(this);
}
}

Solidity: Are these sentences the same? Or do they mean different things?

In order to calling a function 'isContract', with the parameter 'to' being an address, are valid both ways? :
to.isContract()
isContract(to)
Does Solidity allow both ways?
I have found both in different codes, and I don't know if just 'isContract(to)' is the right one, or if 'to.isContract()' means another different thing.
Thanks a lot for your help.
They're not the same.
to.isContract() suggests that you have defined an interface (in your code) that defines a isContract() function, and that the contract deployed at the to address implements this interface.
pragma solidity ^0.8.0;
interface ExternalContract {
function isContract() external returns (bool);
}
contract MyContract {
function foo() external {
ExternalContract to = ExternalContract(address(0x123));
bool returnedValue = to.isContract(); // calling `to`'s function `isContract()`
}
}
isContract(to) calls an external or internal function in your contract.
pragma solidity ^0.8.0;
contract MyContract {
function foo() external {
address to = address(0x123);
bool returnedValue = isContract(to); // calling your function `isContract()`
}
function isContract(address to) internal returns (bool) {
return true;
}
}
Edit: I forgot about one more case - using a library containing the isContract() function for an address. Example OpenZeppelin implementation: definition, usage.
library AddressLibrary {
function isContract (address _address) {
return true;
}
}
contract MyContract {
using AddressLibrary for address;
function foo() external {
address to = address(0x123);
bool returnedValue to.isContract(); // calling your function `isContract(to)`
}