Hardhat cannot console.log msg.data - ethereum

fallback() external {
console.log(msg.data);
(bool result, ) = address(delegate).delegatecall(msg.data);
if (result) {
console.log("SUCESS");
this;
}
}
returns
TypeError: Member "log" not found or not visible after argument-dependent lookup in type(library console).
console.log(msg.data);
^---------^
is there a restriction on what kind of data that can be console.logged?
what does argument-dependent lookup even mean?

the hardhat console library has other functions for different data types. msg.data is calldata so it will be bytes. try console.logBytes(msg.data);
here is the code for console.sol: https://github.com/nomiclabs/hardhat/blob/master/packages/hardhat-core/console.sol

Related

Uniswap PoolAddress.sol error: `TypeError: Explicit type conversion not allowed from "bytes32" to "uint160"`

This is Uniswap PoolAddress library repo
this code is throwing error while I was working on a hardhat project:
function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {
require(key.token0 < key.token1);
//*******************this is causing the error***************
pool = address(
uint160(
keccak256(
abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encode(key.token0, key.token1, key.fee)),
POOL_INIT_CODE_HASH
)
)
)
);
}
I copied the full code on Remix and I get an error for the pool=address line: 'TypeError: Explicit type conversion not allowed from "bytes32" to "uint160".'
I read the docs:
Explicit conversions to and from address are allowed for uint160,
integer literals, bytes20 and contract types.
it also has a warning and I do not understand what it means:
If you convert a type that uses a larger byte size to an address, for
example bytes32, then the address is truncated. To reduce conversion
ambiguity, starting with version 0.4.24, the compiler will force you
to make the truncation explicit in the conversion. Take for example
the 32-byte value
0x111122223333444455556666777788889999AAAABBBBCCCCDDDDEEEEFFFFCCCC.
You can use address(uint160(bytes20(b))), which results in
0x111122223333444455556666777788889999aAaa, or you can use
address(uint160(uint256(b))), which results in
0x777788889999AaAAbBbbCcccddDdeeeEfFFfCcCc.
Since docs mentions that I can convert from bytes20 to int160, I tried this and the error message has gone:
function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {
require(key.token0 < key.token1);
pool = address(
uint160(
bytes20(
keccak256(
abi.encodePacked(
hex'ff',
factory,
keccak256(abi.encode(key.token0, key.token1, key.fee)),
POOL_INIT_CODE_HASH
)
)
)
)
);
}
But I do not think that converting from bytes32 to bytes20 is a valid approach because it will remove some of the hex values in bytes32.
I checked the hardhat.config.ts of the repo and this is the settings that have implemented:
const DEFAULT_COMPILER_SETTINGS = {
version: '0.7.6',
settings: {
evmVersion: 'istanbul',
optimizer: {
enabled: true,
runs: 1_000_000,
},
metadata: {
bytecodeHash: 'none',
},
},
}
Then applied those in
solidity: {
compilers: [DEFAULT_COMPILER_SETTINGS],
...
}

Check if msg.sender is a specific type of contract

As it is now, anyone can call the setMyString function in the FirstContract. I'm trying to restrict access to that function to an instance of SecondContract. But not one specific instance, any contract of type SecondContract should be able to call setMyString.
contract FirstContract{
String public myString;
function setMyString(String memory what) public {
myString=what;
}
}
contract SecondContract{
address owner;
address firstAddress;
FirstContract firstContract;
constructor(address _1st){
owner=msg.sender;
firstAddress=_1st;
firstContract=FirstContract(firstAddress);
}
function callFirst(String memory what){
require(msg.sender==owner);
firstContract.setMyString("hello");
}
}
Solidity currently doesn't have an easy way to validate an address against an interface.
You can check the bytecode, whether it contains the specified signatures (of the public properties and methods). This requires a bit larger scope than a usual StackOverflow answer, so I'm just going to describe the steps instead of writing the code.
First, define the desired list of signatures (1st 4 bytes of keccak256 hash of the name and arguments datatypes) that you're going to be looking for. You can find more info about signatures in my other answers here and here.
An example in the documentation shows how to get any address's (in your case msg.sender) bytecode as bytes (dynamic-length array).
You'll then need to loop through the returned bytes array and search for the 4-byte signatures.
If you find them all, it means that msg.sender "implements the interface". If any of the signatures is missing in the external contract, it means it doesn't implement the interface.
But... I'd really recommend you to rethink your approach to whitelisting. Yes, you'll need to maintain the list and call setIsSecondContract() when a new SecondContract wants to call the setMyString() function for the first time. But it's more gas efficient for all callers of the FirstContract's setMyString() function, as well as easier to write and test the functionality in the first place.
contract FirstContract{
String public myString;
address owner;
mapping (address => bool) isSecondContract;
modifier onlySecondContract {
require(isSecondContract[msg.sender]);
_;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function setIsSecondContract(address _address, bool _value) public onlyOwner {
isSecondContract[_address] = _value;
}
function setMyString(String memory what) public onlySecondContract {
myString=what;
}
}

Contract functionA call contract functionB ,and functionA can storage value

I have a problem about handle function value.
likes the title ..
I already know contract's function call other contract's function depend on:
addr.call(abi.encodeWithSignature("function(parameter_type)", parameter ));
but what if I want to handle the function's value(ex:bool) temporarily (memory) for condition .
I had seen abi.encodePacked() , but I don't even know what parameter feedback to me (compile error , different parameter type), that I can't even storage it .
Some articles write it only for bytes, uint , but I only want to do condition(bool).
You don't need to do that .call unless you want to preserve the msg.sender.
If the msg.sender does not matter for you, I recommend you to look at interfaces. Now, what you have to do, is to create an interface with the functionB definition of that you want to call, and then call it.
Example:
(some deployed contract)
contract MySecondContract {
function functionB() public returns(bool) {
return true;
}
}
(get the deployed contract address and use it in your code like)
interface IMySecondContract {
function functionB() external returns(bool);
}
contract MyFirstContract {
function functionA() public returns(bool) {
bool result = IMySecondContract(MySecondContract-address-here).functionB();
return result;
}
}
If you do want to keep using .call, here you can see that the .call method returns two values.
Something like
(bool success, bytes myReturn) = addr.call(...);
and then this, might work.
Something else that might help is this new way of debugging.

Solidity storage struct not compiling

I'm new to solidity and I'm just experiencing with some simple code.
Basically I just want to create a struct that will store data permenantly inside a contract. According to the doc I need storage for that.
But the following code is not compiling except if I use memory instead. Why?
pragma solidity ^0.4.11;
contract test {
struct Selling {
address addr;
string name;
uint price;
}
mapping(string => Selling) selling;
function sellName() constant returns (bool ok)
{
address a = 0x4c3032756d5884D4cAeb2F1eba52cDb79235C2CA;
Selling storage myStruct = Selling(a,"hey",12);
}
}
The error I get is this:
ERROR:
browser/test.sol:16:9: TypeError: Type struct test.Selling memory is not implicitly convertible to expected type struct test.Selling storage pointer.
Selling storage myStruct = Selling(a,"hey",12);
^--------------------------------------------^
When you first create the myStruct instance, it will be created in memory and then written out to storage (assuming you put the object into your selling map and don't declare your method constant) when the function returns. If you were to retrieve the item from your map in another function, then you would declare it as a storage variable.
See this explanation on Ethereum StackExchange for more details. The Solidity documentation also has a very good explanation of how variables are stored and when to use memory vs storage.
I had similiar situation, the fix for this was:
function sellName() constant returns (bool ok)
{
address a = 0x4c3032756d5884D4cAeb2F1eba52cDb79235C2CA;
Selling memory myStruct = Selling(a,"hey",12);
// insert 'myStruct' to the mapping:
selling[a] = myStruct;
}

How to return array of struct?

Function getBets() gives me the error: error: Failed to decode output: Error: Unsupported or invalid type: tuple. What am I missing?
pragma solidity ^0.4.11;
contract Casino {
struct Bet {
address by;
uint number;
}
address owner;
Bet[] bets;
event BetPlaced(Bet bet);
function Casino() {
owner = msg.sender;
}
function bet(uint number) {
Bet memory bet;
bet.by = msg.sender;
bet.number = number;
bets.push(bet);
BetPlaced(bet);
}
function getBets() constant returns (Bet[]) {
return bets;
}
function getCount() constant returns (uint length) {
return bets.length;
}
}
At the moment if I'm correct you can't return anything except an array of integers as there is no support for returning multi-dimensional data storages;
You can use an experimental library using:
pragma experimental ABIEncoderV2;
in the place of:
pragma solidity ^0.4.11;
This isn't available on Remix if you're using that at the moment and it's experimental so it may never be part of Solidity source: https://github.com/ethereum/solidity/issues/2948
If you did want to return an array of structs you could convert the whole array to bytes and return the bytes. This would be a bit of an extreme case and I wouldn't advise it.
If you only need to access the method internally and not externally you can pass by storage e.g.
function getBets() internal returns (Bet[] storage _r) {
_v = bets;
}
You may want to switch your struct to another contract. This way you can return an array of addresses. I have found using structs is only useful in storing and retrieving "that" data. Contracts are better to return sets of addresses. Also, I have not used the experimental encoder, so just going off of the current solidity version.