Now that we have our mappings to keep track of which trainer owns which pokemon, we'll want to update the contract functions to use them.
In order to do this, we need to use something called msg.sender
.
In Vyper, there are certain global variables that are available to all functions. One of these is msg.sender
, which refers to the address of the person (or smart contract) who called the current function.
Note: In Vyper, function execution always needs to start with an external caller. A contract will just sit on the blockchain doing nothing until someone calls one of its functions. So there will always be a
msg.sender
.
Here's an example of using msg.sender
and updating a mapping:
favoriteNumber: HashMap[address, uint256]
@external
def setMyNumber(myNumber: uint256):
# Update our `favoriteNumber` mapping to store `myNumber` under `msg.sender`
favoriteNumber[msg.sender] = myNumber
@view
@external
def whatIsMyNumber() -> uint256:
# Retrieve the value stored in the sender's address
# Will be `0` if the sender hasn't called `setMyNumber` yet
return favoriteNumber[msg.sender]
In this trivial example, anyone could call setMyNumber
and store a uint256
in our contract, which would be tied to their address
. Then when they called whatIsMyNumber
, they would be returned the uint256
that they stored.
Using msg.sender
gives you the security of the Ethereum blockchain — the only way someone can modify someone else's data would be to steal the private key associated with their Ethereum address.
We need to update the contract functions so that we can create a trainer using the Trainer
struct and trainerList
mapping. This function should also call _createPokemon
function to create a pokemon and then use the trainerToPokemon
mapping to assign the ownership of a pokemon to a trainer. Finally, we would increment the trainerPokemonCount
.
-
Create an event,
NewTrainerCreated
with a single property:name
(String[32]
). -
Create an
external
function namedcreateTrainer
which takes 2 parameters:trainerName
(String[32]
) andpokemonName
(String[32]
). -
Inside the
createTrainer
body, call the_createPokemon
by passingpokemonName
as the_name
parameter. This will return aPokemon
. Create a variablenewPokemon
of typePokemon
and assign its value as the Pokemon returned from_createPokemon
. -
Inside the
createTrainer
body, create a Trainer usingTrainer
struct with thename
value astrainerName
. Create a variablenewTrainer
of typeTrainer
and assign its value as the Trainer created. -
Add the new trainer to the
trainerList
mapping by assigningmsg.sender
tonewTrainer
. -
Add the new trainer and pokemon to the
trainerToPokemon
nested mapping by adding 2 keys: first key asmsg.sender
and second key asself.trainerPokemonCount[msg.sender]
(which acts as a unique key for each pokemon of a trainer). The value assigned isnewPokemon
. -
Increment the
trainerPokemonCount
for our trainer addressmsg.sender
by1
. -
Fire the
NewTrainerCreated
event with the parametertrainerName
.