why empty string is 0x20? - ethereum

Here is my solidity code.
contract TestLog {
bytes constant internal EMPTY_BYTES = "";
event Logempty(bytes data);
function Log() public {
emit Logempty(EMPTY_BYTES);
}
}
so everythime I execute Log(),it print 0x20 in event log, why not 0x00 ?
I deployed it on Ropsten network. Here is the link:
https://ropsten.etherscan.io/address/0xb0723e0943b7b10c985365df6aef983bc6eeb6d6#events

Because the ASCII code of a blank space is actually 0x20. You can read more about those here.
To clarify:
What you are using there, "", is actually the empty string and in most programming languages is different from null. So being a string of length zero, as it's also stated here, there is also memory required to store it.
Hope that helps :)

Related

Gas savings in Solidity arguments -- structs vs encoded bytes

In my smart contract, I have a function that does something (not relevant), but there are two ways I could potentially accept arguments to the function: using a struct, or by encoding the values and simply passing a bytes value like so:
// Only 3 fields for simplicity, but in theory, there could be any arbitrary num. of fields
struct Data {
address user;
uint256 amount;
address receiver;
}
function executeSomething(Data memory data) external returns(bool) {
address user = data.user;
_;
return true;
}
vs
function executeSomething(bytes memory data) external returns(bool) {
address user = (data >> (bytes.length - 160)); // since address is of 160 bytes
_;
return true;
}
In case 1, I'm simply passing a struct, whereas in the second case, I'm passing an argument encoded as bytes memory for which I can extract the argument values by using bitshift tricks.
My question is this:
What are the potential gas savings of these?
Is it more recommended to use a struct (ease of use + sanity purposes)?
Since bytes memory is not of fixed length like bytes32, what is the tipping point in which using a struct makes better sense (gas-savings-wise) than using bytes memory.

Can you help me make sense of this class constructor? (Adafruit_ATParser)

I am building a device for my research team. To briefly describe it, this device uses a motor and load sensor connected to an Arduino to apply a rotational force to a corn stalk and record the resistance of the stalk. We are in the process of building Bluetooth into the device. We are using this BT module.
We have a BLE GATT Service with 2 characteristics for storing DATA and 1 for holding the command which is an integer that will be read by the device and acted on. Reading the command characteristic is where we encounter our problem.
void get_input(){
uint16_t bufSize = 15;
char inputBuffer[bufSize];
bleParse = Adafruit_ATParser(); // Throws error: bleParse was not declared in this scope
bleParse.atcommandStrReply("AT+GATTCHAR=3",&inputBuffer,bufSize,1000);
Serial.print("input:");
Serial.println(inputBuffer);
}
The functions I am trying to use are found in the library for the module in Adarfruit_ATParser.cpp
/******************************************************************************/
/*!
#brief Constructor
*/
/******************************************************************************/
Adafruit_ATParser::Adafruit_ATParser(void)
{
_mode = BLUEFRUIT_MODE_COMMAND;
_verbose = false;
}
******************************************************************************/
/*!
#brief Send an AT command and get multiline string response into
user-provided buffer.
#param[in] cmd Command
#param[in] buf Provided buffer
#param[in] bufsize buffer size
#param[in] timeout timeout in milliseconds
*/
/******************************************************************************/
uint16_t Adafruit_ATParser::atcommandStrReply(const char cmd[], char* buf, uint16_t bufsize, uint16_t timeout)
{
uint16_t result_bytes;
uint8_t current_mode = _mode;
// switch mode if necessary to execute command
if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_COMMAND);
// Execute command with parameter and get response
println(cmd);
result_bytes = this->readline(buf, bufsize, timeout, true);
// switch back if necessary
if ( current_mode == BLUEFRUIT_MODE_DATA ) setMode(BLUEFRUIT_MODE_DATA);
return result_bytes;
}
None of the examples in the library use this. They all create their own parsers. For example, the neopixel_picker example sketch has a file called packetParser.cpp which I believe retrieves data from the BT module for that specific sketch, but it never includes or uses Adafruit_ATParser.. There are no examples of this constructor anywhere and I cannot figure out how to use it. I have tried these ways:
bleParse = Adafruit_ATParser();
Adafruit_ATParser bleParse();
Adafruit_ATParser();
ble.Adafruit_ATParser bleParse();
note: ble is an object that signifies a Serial connection between arduino and BT created with:
SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN);
Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN,BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN);
Can anyone give me a clue on how to use the Adafruit_ATParser() constructor? Also, if the constructor has no reference to the ble object, how does it pass AT commands to the BT module?
I know this is a big ask, I appreciate any input you can give me.
Like this
Adafruit_ATParser bleParse;
You were closest with this one Adafruit_ATParser bleParse();. This is a common beginner mistake because it looks right. Unfortunately it declares a function bleParse which takes no arguments and returns a Adafruit_ATParser object.
I can't answer the second question.
EDIT
I've taken the time to have a look at the code. This is what I found
class Adafruit_BluefruitLE_UART : public Adafruit_BLE
{
and
class Adafruit_BLE : public Adafruit_ATParser
{
what this means is that the Adafruit_BluefruitLE_UART class is derived from the Adafruit_BLE class which in turn is derived from the Adafruit_ATParser class. Derivation means that any public methods in Adafruit_BLE can also be used on a Adafruit_BluefruitLE_UART object. You already have an Adafruit_BluefruitLE_UART object (you called it ble) so you can just use the method you want to use on that object.
SoftwareSerial bluefruitSS = SoftwareSerial(BLUEFRUIT_SWUART_TXD_PIN, BLUEFRUIT_SWUART_RXD_PIN);
Adafruit_BluefruitLE_UART ble(bluefruitSS, BLUEFRUIT_UART_MODE_PIN,BLUEFRUIT_UART_CTS_PIN, BLUEFRUIT_UART_RTS_PIN);
ble.atcommandStrReply( ... );

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;
}
}

Solidity : submit string array, key value pair or an object as parameter to a function

In order to change the state of the smart contract from front end inputs, wanted to submit string array to a smart contract , key value pair or objects.
Is it possible to use string array as parameter?
No solidity doesn't support arrays of strings as parameter. You would have to serialize and deserialize it in a string yourself to have the desired result but that would be expensive to do in solidity. You can test that on remix if you want. However, on remix the error message says that this function is supported in the experimental ABI encoder but I have never tested that, or how well it works with other libraries, and it is experimental after all.
As seen in below example from solidity document we can send bytes array to constructor
constructor(bytes32[] memory proposalNames) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
// For each of the provided proposal names,
// create a new proposal object and add it
// to the end of the array.
for (uint i = 0; i < proposalNames.length; i++) {
// `Proposal({...})` creates a temporary
// Proposal object and `proposals.push(...)`
// appends it to the end of `proposals`.
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
}
If you are trying to send string/Objects data specifically then it's better to separate out the methods and call each methods separately or within each other as currently solidity does not support that (using ABIencodere v2 is exceptional as it is only recommended for development purpose- as per on the date of this answer written)
struct A{
uint date,
B[] b
}
You can separate this out to
struct A{
uint date
}
struct B{
string goods,
uint quantity
}
so now for 1 A you can call N B from your service. Use mapping for binding both(if dependent).
In current situation it's better to design a contract which does not take bulk inputs or give out bulk outputs. However contracts are not for storage of huge data it's for storage of related data which fulfills agreement between parties

Solidity Assembly, the mstore function, and the width of a word in bytes

I'm learning Solidity Assembly and I'm confused about something. I'm looking at this library called Seriality. Specifically, this function: https://github.com/pouladzade/Seriality/blob/master/src/TypesToBytes.sol#L21
function bytes32ToBytes(uint _offst, bytes32 _input, bytes memory _output) internal pure {
assembly {
mstore(add(_output, _offst), _input)
mstore(add(add(_output, _offst),32), add(_input,32))
}
}
That function bytes32ToBytes takes a bytes32 variable and stores it in a dynamically sized bytes array, starting at the offset passed in.
The thing that confuses me is that it uses the mstore function twice. But the mstore function stores a word, which is 32 bytes, right? So why is it called twice, given that the input is 32 bytes? Wouldn't calling it twice store 2 words, which is 64 bytes?
Thanks!
Solidity arrays are stored by writing out the size of the array to the first storage slot then writing out the data to the subsequent slots.
Knowing that mstore has the following parameters: mstore(START_LOCATION, ITEM_TO_STORE), the first mstore statement is written as follows:
mstore(add(_output, _offst), _input)
Since the first slot of the array points to the size of the array, this statement is setting the size of _output. You should be able to get the same result by replacing it with mstore(add(_output, _offst), 32) (since the size is of _input is static).
The second statement (mstore(add(add(_output, _offst),32), add(_input,32))) is the one that writes the data itself. Here, we are shifting the position of both pointers by 32 bytes (as the first 32 bytes for both arrays are pointing to the size) and storing the value of _input to where the data is stored for _output.
Chances are, _output will already be initialized before calling this method (so the length will already be set), so it will usually be unnecessary. But, it doesn't hurt. Note that a similar implementation making this assumption would look like this:
function test() public pure returns (bytes) {
bytes32 i = "some message";
bytes memory o = new bytes(32); // Initializing this way sets the length to the location "o" points to. This replaces mstore(add(_output, _offst), _input).
bytes32ToBytes(0, i, o);
return o;
}
function bytes32ToBytes(uint _offst, bytes32 _input, bytes memory _output) internal pure {
assembly {
mstore(add(add(_output, _offst),32), add(_input,32))
}
}
Not sure about the intention of the function bytes32ToBytes
If it is turning a bytes32 into a bytes, I think the right implementation should be
pragma solidity ^0.7.0;
contract DecodeEncode {
function test() public pure returns (bytes memory) {
bytes32 i = "some message";
bytes memory o = new bytes(32); // Initializing this way sets the length to the location "o" points to. This replaces mstore(add(_output, _offst), _input).
bytes32ToBytes(0, i, o);
return o;
}
function bytes32ToBytes(uint _offst, bytes32 _input, bytes memory _output) internal pure {
assembly {
mstore(add(_output, _offst), 32) //lineA
mstore(add(add(_output, _offst), 32), _input) //lineB
}
}
}
lineA sets the length of the bytes as 32 bytes
lineB sets the content of the first slot of the bytes as _input