I'm making a ballot contract, after a person votes, counter adds 1 to a spesified candidate
mapping(uint256 => mapping(uint256 => uint256)) public voteCountForCandidate;
Here is a mapping with two keys: ProposalID and CandidateID, how do I get a pair with the highest value from it?
Solidity mapping does not support iteration. Generally, everything involving iteration should be avoided in Solidity smart contracts due to gas cost and block size limit issues.
The easiest way to get the highest value mapping is to store the highest value when a new entry is added.
highestValue = max(highestValue, newValue)
Related
Is there a way to avoid trading NFTs on standard marketplaces like OpenSea without breaking the erc721 standard?
If so, how would you go about it?
It is about an NFT that is something like a voucher that can be used 5 times. Over 5 years, once per year. I would like to prevent that someone unknowingly buys a redeemed voucher (for the current year).
You can include checks in your transfer function.
Keep a global map counter with token IDs pointing to the number of transactions per token
mapping(uint256=> uint256) private _tokenTx;
Now, in your transfer function you can use the NFT id, check in the map to see if it's lower than 5, if it is, you fail the tx, otherwise you continue and increase the number
function _transfer(
address from,
address to,
uint256 tokenId
) internal virtual {
require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner");
require(to != address(0), "ERC721: transfer to the zero address");
**require(_tokenTx[tokenId] <6, "ERC721: can\'t transfer more than 5 times");**
_approve(address(0), tokenId);
_balances[from] -= 1;
_balances[to] += 1;
_owners[tokenId] = to;
**_tokenTx[tokenId] = _tokenTx[tokenId]+1;**
emit Transfer(from, to, tokenId);
}
As for filtering exchanges transfers, you can either keep a dynamic list with the addresses they use, or block the approval processes altogether.
The first keeps the standard better but is harder and more expensive to keep up, the second one is a bit more aggressive but will work for all popular exchanges out there
Or, if you're using an external link to redirect buyers/traders to the text file that lists the voucher code, all you have to do is replace the voucher code(s) with a message saying that all the vouchers have been redeemed and then save the file. That way, the next time the NFT gets traded and they unlock the link, they'll see the message.
I sure as hell ain't going to waste my time trying to figure out all that coding nonesense...lol.
I'm traing to get data from an off-chain API to use it in my smart contract. For this, I'm using Chainlink oracle.
I've seen jobs to get one Uint256 or one Bool or a Bytes32 variable. But what if you want to receive an array?
I want to receive something like [1, 2, 3, 4] as an uint[] to be able to loop and use the individual values.
What's the best way to do this?
I already used the Get->Bytes32 and the Get->Bytes, method but then I need to parse these bytes inside the EVM and I don't think that's a good idea.
At the moment arrays are not supported as a response type, here is the list of currently supported response types.
You can:
Read uint256 value by uint256 value, assuming it's a fixed-size array, like this
Make a Multi-Varibale Responses request
Make a Large Responses request, which you mentioned, and handle those bytes32 values. Keep in mind that, currently, any return value must fit within 32 bytes. If the value is bigger than that, make multiple requests.
I have a function that needs to send tokens to a lot of accounts.
I know that a write operation into a store is very costly.
I have read when doing computing on storage it's better to do it on a memory variable and then set this memory variable into the storage and by that save the write operation on storage.
so what I was thinking to do is something like this
mapping (address => uint256) private _balances;
function addToBalance(address[] memory accounts,uint[] memory amounts) public{
mapping (address => uint256) memory balances = _balances;
for(uint i=0;i<accounts.length;i++){
balances[accounts[i]]+=amounts[i];
}
_balances = balances;
}
the _balances mapping can become pretty big. so is it really a better way to reduce the costs?
Not with a mapping.
Mapping (and dynamic-size array) values are all "scattered" in different storage slots. The slot positions are determinable, but because they are calculated based on a hash, the value for key 1 can be in storage slot 123456789 and the value for key 2 can be in storage slot 5. (The numbers are made up just to show an easy example.)
Which means, when you're saving N values into a mapping (under N keys), you always need to write into (the same amount) N storage slots. Writing into one (256bit) slot costs 5,000 gas, and it can add up quickly.
So apart from moving the values into a fixed-size array (which doesn't make much sense in this use case when you're storing balances of an unknown amount of addresses), I'd consider shifting the transaction costs to your users (have a list of eligible users and another list of already used airdrops and let them claim it themselves).
Solidity allows mapping types inside a struct. How many bytes does such a field cost?
Specifically I'd like to optimise the storage layout of the following type.
struct Balance {
uint40 amount;
mapping(address => uint) allowances;
}
I think you mean the storage layout, not memory layout.
uint is an alias for uint256, which is 256-bits. So each value stored in that mapping uses one 32-byte slot in storage.
EDIT
For the full Balance struct, each one will consume two slots in storage, but one slot will always be zero. The first slot is consumed by the uint40, and the second is a placeholder for the mapping that doesn't actually have any value stored. In terms of gas cost, that's free.
So storing a new Balance will write one 32-byte word to storage, and then each uint you add to the allowances mapping will write one 32-byte word to storage.
To learn a bit about ethereum, I thought I'd code up a simple loan contract. I added a few simple properties for any loan, and I immediately ran into problems.
contract Loan
{
address lender;
address borrower;
uint amount;
???? interestRate;
...
}
What type do I use for the interest rate? Looking at the solidity types documentation, the primitive types include Boolean and multiple kinds of integers. There is no primitive for decimal numbers.
Without decimal numbers, how do I calculate the interest?
You can use another unit.
Like multiply every percentage by 100, you achieve a 2 number after comma precision
1% => 100
0,1% => 10
0,01% => 1
If it's not enough, you can use other multipliers.
The Solidity changelog shows that fixed point types will be included in version 0.3.0 which is in development.