In this codpiece, I am finding it hard to figure out what is msg.sender is and how it works internally.
What I am understanding is, we have a mapping favoriteNumber, and the key is an address and the value is a uint.
What is the meaning of comment - "Update our favoriteNumber mapping to store _myNumber under msg.sender, I am understanding that we are updating favoriteNumber, but what does it mean that under msg.sender. What is the role of this method, how it's working?
mapping (address => uint) favoriteNumber;
function setMyNumber(uint _myNumber) public {
// Update our `favoriteNumber` mapping to store `_myNumber` under `msg.sender`
favoriteNumber[msg.sender] = _myNumber;
// ^ The syntax for storing data in a mapping is just like with arrays
}
function whatIsMyNumber() public view returns (uint) {
// Retrieve the value stored in the sender's address
// Will be `0` if the sender hasn't called `setMyNumber` yet
return favoriteNumber[msg.sender];
}
Every smart contract invocation has a caller address. Each EVM (Ethereum Virtual Machine that executes the code) knows which
account carries out each action. In Solidity, you can access the calling account by
referencing msg.sender
So when you call a function of solidity contract, your contract already gets the information of your account, so your account is the msg.sender
favoriteNumber is a mapping. think it like a javascript object. It maps the account addresses to their favourite number.
0x9C6520Dd9F8d0af1DA494C37b64D4Cea9A65243C -> 10
So when you call setMyNumber(_myNumber), you are passing your favourite number. so this number will be stored in favoriteNumber mapping like this:
yourAccountAdress -> yourFavouriteNumber
So when you call whatIsMyNumber function, since EVM already gets your account number, checks in the mappings and returns you your favourite number.
In solidity exists 3 types of variables: state, local and global.
example of global variables:
msg.sender (sender of the message)
msg.value (number of wei sent with the message)
pseudocode from favoriteNumber[msg.sender] = _myNumber;
given a favoriteNumber list,
select the address of the account calling this function,
assign _myNumber to that address
note: global variables are available in all contracts by default. see more info here: solidity docs - global variable
Related
I am wondering about a particular statement in the Moloch v2.1 smart contract code:
https://github.com/Moloch-Mystics/Molochv2.1/blob/main/Flat_Moloch_v2.1.sol
In the Moloch contract, there is a contract level mapping called members
mapping(address => Member) public members;
As expected in almost every line of code that reads or writes to this mapping, square brackets are used. However there is one line of code involving a tuple that uses parentheses instead, wrapping a pair of them around msg.sender:
(,,,bool exists,,) = moloch.members(msg.sender);
Why isn't this line of code using square brackets after the moloch.members reference, like this?:
(,,,bool exists,,) = moloch.members[msg.sender];
I don't understand why that line is using parentheses and what kind of different behavior might result from this. Can someone explain this to me?
For reference purposes, this occurs inside the function below, which is a member of the MolochSummoner contract, which inherits from CloneFactory:
function registerDao(
address _daoAdress,
string memory _daoTitle,
string memory _http,
uint _version
) public returns (bool) {
moloch = Moloch(_daoAdress);
(,,,bool exists,,) = moloch.members(msg.sender);
require(exists == true, "must be a member");
require(daos[_daoAdress] == false, "dao metadata already registered");
daos[_daoAdress] = true;
daoIdx = daoIdx + 1;
emit Register(daoIdx, _daoAdress, _daoTitle, _http, _version);
return true;
}
You can only use brackets if you are accessing the variable inside the same contract.
Outside the contract, when accessing a public variable you are calling a getter function members(). Solidity automatically generates this function for you. There is no get prefix.
More about Solidity getter functions here.
This is a bit confusing and somewhat bad design decision, so I apologize.
I've been following my new journey into learning Solidity. Now I'm into a structs + Data locations course, and I came to a situation when I didn't use the exact same example as the instructor did, both works. I would like to know which one is technically more correct.
Concerning the way the instructor did, I understand that if that data variable already exists, filled with data, and we're using it on a Storage, that would be understandable but for the Memory case, I still don't get the meaning of it.
Here are the two exmples:
Mine:
struct PERSON {
uint256 id;
string name;
}
PERSON public personList;
function updateNewPerson(uint256 _index, string memory _name) public {
PERSON memory newUpdatedPerson;
newUpdatedPerson.name = _name;
personList[_index] = newUpdatedPerson;
}
Instructor code:
struct PERSON {
uint256 id;
string name;
}
PERSON public personList;
function updateNewPerson(uint256 _index, string memory _name) public {
PERSON memory newUpdatedPerson = personList[index];
newUpdatedPerson.name = _name;
personList[_index] = newUpdatedPerson;
}
This is the same example with Storage data location I'm reffering to:
function updateStoragePerson(uint256 _index, string memory _name) public {
PERSON storage newUpdatedPerson = personList[_index];
newUpdatedPerson.name = _name;
}
I'm trying to figure out the is there's any difference there and i think I'm starting to uderstand it, and please correct me if I'm wrong.
So in my example I'm basically just passing the new user insert new value, which is in this case _name, then when giving it back to the array handing it to its position through the index array.
When on the instructor example, he's passing through the array index case content, which is id and name, then insering the new name value from the function before passing back the data to the array, and in this case id and _name are identical.
What I can see is that, in your code, when you create a newUpdatedPerson, you are creating an empty variable of type PERSON, and then you only fill it with the name, whereas your instructor takes the original value from a person which already exists and then updates its value. This will result in your newUpdatedPerson in your personList to update its name but its id will become empty.
The newUpdatedPerson will be stored in personList as copies from storage to local storage actually copy a reference to the storage so any update on newUpdatedPerson will result in an update to personList.
Assignments from storage to a local storage variable also only assign a reference.
I hope you find this information helpful :)
State variables are storage by default (values are stored in the blockchain).
Local variables in functions are memory by default (values are stored temporarily in memory).
Structs are storage by default (values are stored in the blockchain).
I explained how memory and storage type behave differently on this stackoverflow post
I am just starting with language-ext, trying to use it in my Azure Function.
In this function, I first parse/validate the POSTed data from the HTTP request using some validator.
This validator returns an Either<ValidationErrors, RequestModel>.
Then I would like to chain onto the either result a service call that should use the request model to grab some data from an API an return an Option.
At the end of the chain I would then like to return an IActionResult BadRequest if there were ValidationErrors in the first step, or otherwise perform a Match on the result of the service call Option to either return a NotFoundResult or ObjectResult.
The issue I run into is that if I want to chain my service call (using Bind, or BiBind) after the Either<ValidationErrors, GetRequestModel>, then the signature of my service method must be some Either<ValidationErrors, ...>, which is incorrect, since my service method has nothing to do with ValidationErrors. It should just return an Option.
So I guess my question is how can preserve any ValidationErrors until the end of the chain, and be able to chain my service call with a Option signature onto an Either?
You have to decide what the result of your chained expression is.
Option:
var maybeResult = from validated in GetValidationResult(...).ToOption()
from apiResult in ApiCall(...)
select apiResult;
Either:
var resultOrError = from validated in GetValidationResult(...)
from apiResult in ApiCall(...).ToEither(*LEFT*)
select apiResult;
You have to replace *LEFT* by some error value or error generating function returning same type like left type of GetValidationResult.
Replace above pseudo code with your own code and look at the return types of the functions used above to see what's going on.
The reason why you need a common left type is that the bind operation can return some left (error) of first (GetValidationResult) or second (ApiCall) function call -- or right of your last (ApiCall) function if your reach successful end of your chain.
Recommendation: If you mix different left (error) return types you might want to use some thing like LanguageExt's built-in Error type or maybe just a plain string (or Exception).
Either with string as error type:
var resultOrError = from validated in GetValidationResult(...).MapLeft(Prelude.toString)
from apiResult in ApiCall(...).ToEither("api call failed")
select apiResult;
Additional note: I use LINQ style here, you can use method style:
var resultOrError = GetValidationResult(...)
.MapLeft(Prelude.toString)
.Bind(validated => ApiCall(...)
.ToEither("api call failed"));
What is the proper/recommended method to pass data between the callbacks in a C module in FreeRADIUS?
For example, I want to create a unique request_id for the request and use it for all log entries during that request. If I create this value inside mod_authorize, how do I pass it over to mod_authenticate on the same request thread, and how do I retrieve it?
static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, REQUEST *request)
{
// Generate uuid
uuid_t uuid;
uuid_generate_random(uuid);
// Convert to a string representation
char *request_id = talloc_array(mem_ctx, char, UUID_STR_LEN);
uuid_unparse(uuid, request_id);
// Do stuff and log authorize messages
radlog(L_INFO, "request_id inside mod_authorize: %s", request_id);
// How do I pass request_id to mod_authenticate callback
// ?????????????
return RLM_MODULE_OK;
}
static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(void *instance, REQUEST *request)
{
char *request_id = NULL;
// How do I retrieve the request_id value
// ???????????????????
// Do stuff and log authenticate messages
radlog(L_INFO, "request_id inside mod_authenticate: %s", request_id);
return RLM_MODULE_OK;
}
Attaching the value to the request object seems like a logical thing, but I don't see a way of doing it, other than adding a value pair to the request->reply (and I don't want to return this value to NAS).
Thank you.
Apparently, there is a range of "Temporary attributes, for local storage" (defined in the dictionary.freeradius.internal file) that can be used with one of the requests object's collections (request->config, request->reply->vps and request->packet->vps). You can find the start of this range by searching dictionary.freeradius.internal file in the FreeRADIUS repository for
ATTRIBUTE Tmp-String-0
In this case I found request->packet->vps to be appropriate, and used Tmp-String-3 to add my request_id to it while inside MOD_AUTHORIZE callback:
pair_make_request("Tmp-String-3", request_ctx->request_id, T_OP_EQ);
where pair_make_request is a macro defined as
fr_pair_make(request->packet, &request->packet->vps, _a, _b, _c)
I then retrieved it, while inside MOD_AUTHENTICATE callback:
VALUE_PAIR *vp = fr_pair_find_by_num(request->packet->vps, PW_TMP_STRING_3, 0, TAG_ANY);
The numerical values of these attributes change between the versions, you must use macro definitions instead
The macros for these attributes, such as PW_TMP_STRING_3 in the esample above, are located in the file "attributes.h" which is auto-generated during the build. Here is a quote from Arran Cudbard-Bell, that I found here:
If you really want to know where each one is used, download,
configure, build the source. Then see src/include/attributes.h for the
macro versions, and grep -r through the code. That'll at least tell
you the modules, and if you're familiar with C you should be able to
figure out how/when they're added or checked for. – Arran Cudbard-Bell
Apr 12 '15 at 20:51
In my case, the resulting file is located at /usr/include/freeradius/attributes.h
I must say that it took me unreasonable amount of effort to track this information down. There is no other trace, none whatsoever, of these attribute macros. Not in the code, not in the FreeRADIUS documentation, not in Google search results.
I am currently doing the facebook relayjs tutorial and I need help understanding this part of the tutorial, it states
Next, let's define a node interface and type. We need only provide a
way for Relay to map from an object to the GraphQL type associated
with that object, and from a global ID to the object it points to
const {nodeInterface, nodeField} = nodeDefinitions(
(globalId) => {
const {type, id} = fromGlobalId(globalId);
if (type === 'Game') {
return getGame(id);
} else if (type === 'HidingSpot') {
return getHidingSpot(id);
} else {
return null;
}
},
(obj) => {
if (obj instanceof Game) {
return gameType;
} else if (obj instanceof HidingSpot) {
return hidingSpotType;
} else {
return null;
}
}
);
On the first argument on nodeDefinition,where did it get its' globalId? is Game and HidingSpot a name on the GraphQLSchema? What does this 'const {type, id} = fromGlobalId(globalId);' do? and also what is the 2nd argument? I need help understanding nodeDefinitions, somehow I can't find nodeDefinitions on the official documentation. Thank you.
If you were writing a GraphQL server without Relay, you'd define a number of entry points on the Query type, eg:
type Query {
picture(id: Int!): Picture
user(id: Int!): User
...etc
}
So when you want to get a User, you can easily get it because user is available as an entry point into the graph. When you build a query for your page/screen, it'll typically be several levels deep, you might go user -> followers -> pictures.
Sometimes you want to be able to refetch only part of your query, perhaps you're paginating over a connection, or you've run a mutation. What Relay's Node interface does is give you a standard way to fetch any type that implements it via a globally unique ID. Relay is capable of recognising such nodes in its queries, and will use them if possible to make refetching and paginating more efficient. We add the node type to the root Query type:
type Query {
picture(id: Int!): Picture
user(id: Int!): User
...etc
node(id: ID!): Node
}
Now for nodeDefinitions. Essentially this function lets us define two things:
How to return an object given its globalId.
How to return a type given an object.
The first is used to take the ID argument of the node field and use it to resolve an object. The second allows your GraphQL server to work out which type of object was returned - this is necessary in order for us to be able to define fragments on specific types when querying node, so that we can actually get the data we want. Without this, we couldn't be able to successfully execute a query such as this:
query Test {
node(id: 'something') {
...fragment on Picture {
url
}
...fragment on User {
username
}
}
}
Relay uses global object identification, which means, in my understanding, if your application ever try to search for an object. In your example, try to look for a game, or try to look for a hidingSpot. Relay will try to fetches objects in the standard node interface. i.e. find by {id: 123} of the Game, or find by {id:abc} of the hidingSpot. If your schema (Game, HidingSpot) doesn't set up the node interface, Relay will not be able to fetch an object.
Therefore, if your application requires a search in a "Game", in the schema, you need to define the node interfaces.
By using graphql-relay helper, use nodeDefinitions function only once in your application to basically map globally defined Ids into actual data objects and their GraphQL types.
The first argument receives the globalId, we map the globalId into its corresponding data object. And the globalId can actually be used to read the type of the object using fromGlobalId function.
The second function receives the result object and Relay uses that to map an object to its GraphQL data type. So if the object is an instance of Game, it will return gameType, etc.
Hope it will help you understand. I am on my way learning, too.