How to check for negative numbers sent to smart contract? - ethereum

I want my contract not to accept negative values being added to it's balance, so I thought I'd add a require value > 0. It seams though as the value sent with the payable function is unsigned and therefore always a positive number. Meaning if you send -1 ether it is accepted and adds about 1 ether instead. How do I make sure no negative numbers can be sent?
function () external payable {
require(msg.value > 0);
require(msg.data.length == 0);
}
Thanks!

It is impossible to send a negative value in EVM. So msg.value is always non-negative. You don't need to check that.

Related

UniswapV2Pair, mint function, how is liquidity is created proportion to pair liquidity added

function mint(address to) external lock returns (uint liquidity) {
}
The function above is implemented such that liquidity is added to the to address, however the liquidity is just minted depending on the difference of reserves and balance of token how will it create the liquidity in proportion to liquidity added by sender,
Am i missing something, what if a user always calls the mint function will he not get free LP token added to the address as we can see that the mint function is external not internal
Am i missing something, what if a user always calls the mint function will he not get free LP token added to the address as we can see that the mint function is external not internal
You are missing the function body and all the logic and checks inside it.
what if a user always calls the mint function will he not get free LP token added to the address
The mint() function itself only mints LP tokens to make up for a difference between actual LP balance and expected LP balance. If there's no difference between the actual and expected balances, no LP tokens are minted.
A common practice is to use the router function addLiquidity() which sends tokens to the Pair contract, and then invokes the mint() function - both as part of one transaction, so there's no way to frontrun this action.
If there were underlying tokens sent to the Pair contract without invoking the mint() function, then anyone could invoke this function freely claiming LP tokens representing this difference. However only once, as the LP mint zeros up the difference.
what if a user always calls the mint function will he not get free LP
token added to the address as we can see that the mint function is
external not internal
mint() is called when a user added liquidity.
however the liquidity is just minted depending on the difference of
reserves and balance of token how will it create the liquidity in
proportion to liquidity added by sender,
Because the main equation is based on increasing liquidity is proportional to an increase in LP token shares. This makes sense because adding liquidity has no effect on price, so if you add more liquidity, you should receive LP tokens proportional to what you have received before
Let's say you have T shares and you want to increase liquidity from L0 to L1. How many more shares will be minted for you?
L1 / L0 = (T + mintAmount)/T
We need to find mintAmount.
(L1/L0) * T = T + mintAmount // leave mintAmount alone
((L1/L0)*T) - T = mintAmount // multiply T with L0/L0
((L1/L0)*T) - (T*L0)/L0 = mintAmount
Finally
mintAmount = ((L1-L0)/L0) * T

Block OpenSea trading

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.

Best way to register for a vote in solidity

Hi I'm creating a voting smart contract for a DAO and I have a security question. The voting system works like this:
You send your tokens to the smart contract then the smart contract registers how much tokens you have and assignes you "Power" which you use when you vote. Then the smart contract sends the funds back immidiately.
My question is if there is more secure way to do this. Without funds leaving usere's wallet.
Here is the code I have so far.
function getPower() payable public {
require(msg.value > 0, "The amount can't be 0");
require(election_state == ELECTION_STATE.OPEN);
require(votingPeriod > block.timestamp);
uint amountSent = msg.value;
// This function will take their money and assign power to the voter
// The power is equal to their deposit in eth * 10 so for each eth they get 10 power
voters[msg.sender].power = msg.value * 10;
payable(msg.sender).transfer(amountSent);
}
Thanks in advance.
Based on the provided code and question, I'm assuming you want to calculate the voting power based on the users' ETH balance - not based on their balance of the DAO token.
You can get the current ETH balance of an address, using the .balance member of an address type. So you could simplify your function as this:
function getPower() public {
require(election_state == ELECTION_STATE.OPEN);
require(votingPeriod > block.timestamp);
voters[msg.sender].power = msg.sender.balance * 10;
}
After performing the validations, it assigns the value based on the msg.sender ETH balance at the moment of the getPower() function being invoked. Without them needing to send ETH to the contract.
Note that this approach is not common and can be misused for example by users loaning a large amount of ETH just before executing the getPower() function. I'd recommend you to use a more common pattern of calculating the voting power based on their current holdings of the token representing their stake in the DAO.

how to transfer fund from msg.sender(amount) to recipient address without using setting msg.value

We can transfer funds from address(this) to recipient. But is there any way to transfer funds directly msg.sender wallet to recipient? I can not set msg.value at the time of invoking payoutBonus call. Because I can get the amount only inside payoutBonus method.
function payoutBonus(address recipient) public payable returns (bool) {
// bonus = calculateBonus();
//transfer this bonus to recipient from msg.sender;
return true;
}
msg.value is a read-only property reflecting value of the incoming transaction. If you want to send an ETH amount, you can do it in one of two ways.
Notes:
These examples work on Solidity 0.8. Some previous versions also allow the send() method that is now deprecated, don't require the payable type, and have slightly different syntax for the call() method.
bonus is amount of wei (1 ETH is 10^18 wei)
The transfer() method
uint256 bonus = calculateBonus();
payable(msg.sender).transfer(bonus);
The transfer() method only allows consuming 2300 gas, which is enough for non-contract recipients. If the recipient is a contract requiring more than 2300 gas to receive the ETH (for instance it sets some local variable), the transaction reverts.
Low-level call()
uint256 bonus = calculateBonus();
msg.sender.call{value: bonus}("");
With the low-level call() method, you can also specify the gas limit, function to call and it's arguments. Use this method only if you know what you're doing.

Transfer money between accounts in solidity

I am writing a contract where I want to transfer money (present in the contract owners account and not the contract) to an account address passed to a function in the contract.
for some reason this code won't work
function payBill(uint value, address account) payable public {
account.transfer(value);
transactionCount += 1;
transactionAmount += value;
}
Your problem can be related to any frontend code, not only this.
You've got two options.
get that other user address from the contract and then run a direct transaction between two accounts (example here https://web3js.readthedocs.io/en/v1.2.6/web3-eth.html#id80)
send a value (see here https://web3js.readthedocs.io/en/v1.2.6/web3-eth-contract.html#id33) when you are calling the payBill method. If you don't do it, the default value is zero, and you don't see any transfer.
Also, please consider having a look at this https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/
EDIT:
what you are trying to do here, is also not doable. This requires the contract to have the number of funds that you want to transfer. That is because, with the payable method, you are sending funds to the contract, but the funds will only be in the contract, once the transaction is accepted. On the other hand, you are trying to send that number of funds to another user, without having them on the contract. That is why you never see any balance.