is there any way for solidity 0.4.24 get bytes data from call - solidity

I am trying to follow this trick.
https://blog.polymath.network/try-catch-in-solidity-handling-the-revert-exception-f53718f76047
For solidity version 5 all works and I can do this:
(bool success, bytes memory returnData) =
address(token).call(...)
For solidity version 4 I can do only this:
(bool success) =
address(token).call(...)
If I am trying get returnData in v4 I get this err
TypeError: Not enough components (1) in value to assign all variables
(2).
is there any way to get returnData for Solidity v 4 ? Without double call?
I need this data for case not to make a double call when I need to check the view function, this can be called or not on contracts.

Yes, this is only possible in version 5 and newer
https://solidity.readthedocs.io/en/v0.5.0/050-breaking-changes.html

Related

Why does this solidity function run into gas errors?

I'm trying to figure out some strange behavior. The function below takes in an array like [1,2,3,4,5], loops through it, and looks at another contract to verify ownership. I wrote it like this (taking in a controlled / limited array) to limit the amount of looping required (to avoid gas issues). The weird part (well, to me) is that I can run this a few times and it works great, mapping the unmapped values. It will always process as expected until I run about 50 items through it. After that, the next time it will gas out even if the array includes only one value. So, I'm wondering what's going on here...
function claimFreeNFTs (uint[] memory _IDlist) external payable noReentrant {
IERC721 OGcontract = IERC721(ERC721_contract);
uint numClaims = 0;
for (uint i = 0; i < _IDlist.length; i++) {
uint thisID = _IDlist[i];
require(OGcontract.ownerOf(thisID)==msg.sender, 'Must own token.' );
if ( !claimedIDList(thisID) ) { // checks mapping here...
claimIDset(thisID); // maps unmapped values here;
numClaims++;
}
}
if ( numClaims > 0 ) {
_safeMint(msg.sender, numClaims);
emit Mint(msg.sender, totalSupply());
}
}
Any thoughts / directions appreciated. :-)
Well, there was a bit more to the function, actually. I'd edited out some of what I thought was extraneous, but it turned out my error was in the extra stuff. The above does actually work. (Sorry.) After doing the mint, I was also reducing the supply of a reserve wallet on the contract -- one that held (suprise!) 50 NFTs. So, after this function processed 50, it was making that wallet hold negative NFTs, which screwed things up. Long story, but on Remix, I'd forgotten to set values in the constructor in the proper order, which is how I screwed it up in the first place. Anyway, solved.

Solidity -- using uninitialized storage pointers safely

I'm trying to gas-optimize the following solidity function by allowing users to sort the array they pass in such a way that I can perform less storage reads. However, to do this I need to use an uninitialized storage pointer -- which the compiler doesnt let me do (^0.8.0). How can I safely use an uninitialized storage pointer and have it be accepted by the compiler?
function safeBatchReleaseCollaterals(
uint256[] memory bondIds,
uint256[] memory collateralIds,
address to
) public {
// 'memoization' variables
uint256 lastAuthorizedBond = 2**256 - 1;
uint256 lastCurrencyRef = 2**256 - 1;
Currency storage currency;
for (uint256 i = 0; i < bondIds.length; i++) {
uint256 bondId = bondIds[i];
// check if we authorized this bond previously?
if (lastAuthorizedBond != bondId) {
require( // expensive check. Reads 2 slots!!
_isAuthorizedToReleaseCollateral(bondId, msg.sender),
"CollateralManager: unauthorized to release collateral"
);
lastAuthorizedBond = bondId;
}
uint256 collateralId = collateralIds[i];
Collateral storage c = collateral[bondId][collateralId];
// check if we read this Currency previously?
if (lastCurrencyRef != c.currencyRef) {
currency = currencies[c.currencyRef]; // expensive 1 slot read
lastCurrencyRef = c.currencyRef;
}
_transferGenericCurrency(currency, address(this), to, c.amountOrId, "");
emit CollateralReleased(bondId, collateralId, to);
}
}
As a quick explanation of the structure: this is similar to a batch erc1155 transfer, except I'm storing a lot of data related to the transaction in some slots under the Currency and Collateral and Bond objects. Since the reads can get intensive, I want to optimize gas by caching reads. Since having an actual cache map is also expensive, I instead optimize by caching only the previous list item, and rely on the user to sort the array in such a way that results in the smallest gas costs.
The lastAuthorizedBond variable caches which bondId was last authorized -- if it repeats, we can cut out an expensive 2-slot read! (which results in maybe 16% gas savings during tests. You can see, significant). I tried doing something similar with the currency read, storing the lastCurrencyRef and hoping to store the actual result of the read into the currency variable. The compiler complains about this however, and maybe justly so.
Is there a way to pass this by the compiler? Do I just have to ditch this optimization? Though nobody is allowed to register the 2**256-1 currency or bond, is this code even safe?
Note that the collateral entry gets deleted after this runs -- cannot double release.

Solidity how to get random number with ratio

I want to create my own NFT according to ERC1155 standard.
My hero has 6 parts, each part has 4 types as shown in the picture.
Now I want to create a function that takes a random number with the ratio shown in the image.
Here is simple function return random number. With _mod = 10^n it will return number of length n-1.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract RandomNumbers{
function random(uint _mod) public view returns(uint){
return uint(keccak256(abi.encodePacked(block.timestamp,block.difficulty,
msg.sender))) % _mod;
}
}
I've been struggling with this for a whole day.
Thanks for help.
Just so you know. You shouldn't use keccak256(abi.encodePacked(block.timestamp,block.difficulty,msg.sender)) to generate a random number because that actually creates a pseudo-random guessable number. Take a look at Chainlink VRF.
For the ratio you could try to check out this Data structure (GitHub): you manually set values for the leaves and then when you have your random number you can call the draw function to set the different stats.

Uniswapv2 addLiquidity Decimal error in Remix (Bignumber)

I'm testing Uniswapv2 for a project and am getting this error:
transact to UniswapV2Router02.addLiquidity errored: Error encoding arguments: Error: invalid BigNumber string (argument="value", value=".004", code=INVALID_ARGUMENT, version=bignumber/5.1.1)
The Uniswapv2 code is normal and unedited. I tested these number on Uniswap itself to make sure the numbers worked before I tried them in Remix. These are what I tried to pass:
tokenA: 0xc778417e063141139fce010982780140aa0cd5ab (WETH since I can't find ETH address)
tokenB: 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 (UNI)
amountADesired: 0.004
amountBDesired: 0.03
amountAMin:1
amountBMin:2
to: 0xd50eCE9501a1f63e449DbBBbBdc5CB59f3e2c231
deadline: 255
Solidity contracts don't take decimal arguments. Instead, you need to pass the amount of smallest units.
WETH (note - you have an incorrect address in your question) has 18 decimals, UNI has 18 as well.
1 WETH is 1000000000000000000 (or 10^18) units.
So if you want to pass 0.004 WETH in the argument, you need to input the number 4000000000000000 (which is 0.004 * 10^18).
Note: ETH is the native currency of the Ethereum network, so there is no token address for ETH. Uniswap v2 Router 2 has a function addLiquidityETH() for when you want to add liquidity to a pair of a token to ETH.

Multiplication and Division with contract value

I am trying to insert a if-clause in the following contract to check if the withdrawal (it is a sample bank contract) is less than the 10% of the whole contracts value, i.e. of the complete bank.
When I insert the code as below it gives me an error such as
"UnimplementedFeatureError: Not yet implemented - FixedPointType."
What am I doing wrong?
Can you help me?
Many thanks in advance!!
pragma solidity ^0.4.24;
contract bank{
mapping (address => uint) private balance;
address public Owner;
function WithDrawMoreMoney(uint a) public{
require (balance[msg.sender]>=0);
require (address(this).balance>=0);
require ((a) =< (address (this).balance)*(uint(1.1))); // The problematic line
balance[msg.sender]-=a;
(msg.sender).transfer(a);
check if the withdrawal ... is less than [10%] of the whole [contract's] value
I think you just want this:
require(a <= address(this).balance / 10);
Your code multiplied by 1.1 when I think you meant 0.1, but either way Solidity only has integers. Dividing by 10 works. You also had a typo: =< instead of <=.
If you want to check some other percentage, like 23%:
require(a <= address(this).balance * 23 / 100);
Make sure to do the multiplication first, and always remember to guard against integer overflows.