Contract Predecessor vs Signer vs Current - smartcontracts

Can someone help me understand the relationship and distinction amongst these three concepts? It seems like context.predecessor == context.contractName checks are common.

signer - account that signed the initial transaction.
predecessor - the last account who made the current contract call.
current - the account of the contract.
For an example, consider contract contract.near and a user alice.near.
alice.near calls method foo on contract.near. In the context of foo:
signer == alice.near
predecessor == alice.near
current == contract.near
Then if a promise call is made to another method say faa, then its context is:
signer == alice.near
predecessor == contract.near
current == contract.near
So the check predecessor == current or context.predecessor == context.contractName is to make sure that the contract was the account that made the contract call. A method with this assertion is considered "private" because only the contract can call it even though it is part of a public facing API.

The answer from sirwillem above explains it well
Just remember the idea behind assertions like context.predecessor == context.contractName can be:
Calling private methods in a contract indirectly (which can only be called by the contract itself)
Calling admin level methods that only the contract id (contract owner) should call

Related

ERC20 totalSupply Best practice

Best Practice Advice:
Is it acceptable to override the totalSupply() of an ERCToken if you're using a different variable to hold some of the supply and not holding all the tokens in the totalSupply variable directly?
example:
...
uint _extraSupplyForGivingAway = 1e27; //decimal 1e18 * 1M just an example
function totalSupply() public view override returns(uint totalSupply){
totalSupply = super.totalSupply() + _extraSupplyForGivingAway);
return (totalSupply);
}
The total value of the contract is not only the _totalSupply, it's also the _totalSupply and the extra tokens.
Question: Does the community and/or exchanges find this acceptable or not?
There are two different issues here. One is, are you conforming to the EIP-20 (ERC-20) standard in a way that will be understood by the community-at-large? Another is, is this a reasonable implementation for your business logic?
The latter issue is out-of-scope here since you haven't really provided enough information. So I will address the first, which is what I believe you wanted to know.
The reason I spell this out is because you fixate on implementation details but ERC20 is an interface standard, so it doesn't by-and-large dictate how things ought to be implemented.
In the case of totalSupply, all the standard says is:
totalSupply
Returns the total token supply.
function totalSupply() public view returns (uint256)
If it's not clear what that means, the EIP does link to the OpenZeppelin contract as an example implementation, which has:
/**
* #dev Total number of tokens in existence
*/
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
So as long as the total number of minted tokens is returned, you are fine. It doesn't matter if you internally have it computed as the sum of two other private variables. I do have some lingering doubts about your implementation from what you wrote, but as I said, that's out-of-scope :)
I hesitate to add this and possibly muddy the waters but.. "tokens in existence" is somewhat ambiguous. Sometimes people have their burn function do an actual transfer to the zero address (not just the event), effectively removing them from the circulating supply, and adjust the total supply accordingly. So their totalSupply will then return the number of tokens held only by non-zero addresses. Block explorers may or may not account for this. I would avoid doing this unless you absolutely know what you're doing.

How to call _mint() on erc721 without emit Transfer

I've read here that it is possible to mint 2^256 nfts in a single transaction. I've tried to achieve this by directly assigning _owners and _balances mappings but ofc these are private variables so i can't change them. I tried making an _mint() override but that also didn't work. How does this process work?
For simplification, let's do a 10k NFTs scenario.
It's not about invoking a single mint() function 10k times, rather than building your contract logic in a way that allows setting up a range of valid IDs.
Using the MFS part of IPFS, you can upload multiple files into a folder using the same directory ID and actual file names. Example:
https://ipfs.io/ipfs/<dir_id_abc>/1.json
https://ipfs.io/ipfs/<dir_id_abc>/2.json
https://ipfs.io/ipfs/<dir_id_abc>/3.json
etc...
These metadata files contain links to the images.
Your contract can then implement a custom function that shadows an authorized address as an owner of the NFT if both following conditions are met:
The ID is in a valid range (in our case 1-10k)
The NFT is not owned by anybody else (i.e. it's owned by the default address 0x0)
function _exists(uint256 tokenId) override internal view returns (bool) {
if (tokenId >= 1 && tokenId <= 10000) {
return true;
}
return super._exists(tokenId);
}
function ownerOf(uint256 tokenId) override public view returns (address) {
address owner = _owners[tokenId];
// The ID is in a valid range (in our case 1-10k)
// The NFT is not owned by anybody else (i.e. it's owned by the default address 0x0)
if (tokenId >= 1 && tokenId <= 10000 && owner == address(0x0)) {
// shadows an authorized address as an owner
return address(0x123);
}
return super.ownerOf(tokenId);
}
The tokenURI() function then validates the token existence (using the _exists() function) and returns the final URI concatenated from the base URI (https://ipfs.io/ipfs/<dir_id_abc>/), the ID, and the .json suffix.
Mind that this approach does not work on the OpenZeppelin implementation, as their _owners property is private and not readable from child contracts. But you can take this snippet as an inspiration for a custom implementation that allows simulating an arbitrary default owner of 10k (or even 2^256) tokens.
Tbh I don't know how that could be possible without paying ungodly amounts of gas. Why are you trying to mint that many tokens? Are you trying to get all the NFTs in a collection? If so, you'll have to pay the gas costs for every mint regardless.

Uniswap V2 ERC20 token solidity code: Are token names hard coded?

I was reimplementing the Uniswap v2 contracts and I just could not figure this out.
https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol
So, from what I understand :
If a pair exchange / liquidity pool doesn't exist upon adding liquidity, the UniswapFactory.sol creates a new LP pool contract.
This pool contract UniswapV2pair.sol itself is an ERC20 contract. However, I have some questions about the UniswapV2ERC20 contract it inherits from.
https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2ERC20.sol
It seems like the name and symbol are hard coded into the contract with
string public constant name = "Uniswap V2;
string public constant symbol = 'UNI-V2';
, so when "name" is called from a frontend to the liquidity pool contract, it will always return the string" Uniswap V2" , regardless of what the underlying LP token is (like DAI- ETH, USDC-ETH.. etc).
Is my understanding of this correct? I know the functionality should be fine regardless as all these Pair Liquidity pool contracts are deployed as separate contracts but it seemed a little odd to me that the name and symbol couldn't just be set as something like "DAI-ETH LP" in the constructor rather than all as the same "uniswap v2".
Thanks
You're reading the code correctly. Uniswap has decided to set the same name for all LP token contracts (i.e. pair contracts).
This approach puts more emphasis on the actual pair token addresses, rather than names.
If a pair name contained the token names, a dishonest author could create a custom token named USDT, a Uniswap pair named "ETH-USDT LP", and lure users who won't check the token address into selling their ETH for an otherwise worthless token (instead of the "real" USDT).

How to handle return errors in solidity view functions?

I have contract, which use another contract, which receives a pair of tokens, and returns the best price by comparing several exchanges.
Problem is if such tokens pair is not on the contract exchanges list, the contract returns an error.
I need just something like this for solidity 0.4.24, for a view function (not send)
try{
// get return from contract A
}catch{
// get return from contract B
}
I found solution with abi.encodeWithSelector()

best practice for return value in WCF services

I have a WCF service sitting in the cloud.
And my application makes several calls to this WCF service.
Is it a best practise:
1] to always use return value as bool which indicates if the operation was sucessful or not.
2] returning the values you meant to return as the OUT parameters
I would:
return an atomic value (bool, string, int) if appropriate
return a complex type (a class instance) if I need to return more than one value - make sure to mark that class with [DataContract] and its properties with [DataMember]
a SOAP fault FaultException<T> when an error occurs; the <T> part allows you to define your own custom error classes, and again - don't forget to mark them with [DataContract] / [DataMember] and declare them as FaultContract on your operations
1] to always use return value as bool which indicates if the operation was sucessful or not
Yes, if the operation isnĀ“t time consuming AND the return status is always relevant:
Waiting on a return value can affect both client and service host(server) performance/scalability. Ex. in a Request-Responsecall, Requests can keep connections open for a long preriod of time waiting for operation completion. You could implement in a way similar to "HTTP 202 Accepted" status code usage(i.e operation received arguments and has started(patially), but does wait for the completion)
No, if the operation logic only makes sense if synchronous.
No, if you are keen on refactorability/maintainability ex. when you want to return include an error message/code in the return.
2] returning the values you meant to return as the OUT parameters
Yes, this makes the service operation more wsdl compliant and easy to read.