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,
NewTrainerCreatedwith a single property:name(String[32]). -
Create an
externalfunction namedcreateTrainerwhich takes 2 parameters:trainerName(String[32]) andpokemonName(String[32]). -
Inside the
createTrainerbody, call the_createPokemonby passingpokemonNameas the_nameparameter. This will return aPokemon. Create a variablenewPokemonof typePokemonand assign its value as the Pokemon returned from_createPokemon. -
Inside the
createTrainerbody, create a Trainer usingTrainerstruct with thenamevalue astrainerName. Create a variablenewTrainerof typeTrainerand assign its value as the Trainer created. -
Add the new trainer to the
trainerListmapping by assigningmsg.sendertonewTrainer. -
Add the new trainer and pokemon to the
trainerToPokemonnested mapping by adding 2 keys: first key asmsg.senderand second key asself.trainerPokemonCount[msg.sender](which acts as a unique key for each pokemon of a trainer). The value assigned isnewPokemon. -
Increment the
trainerPokemonCountfor our trainer addressmsg.senderby1. -
Fire the
NewTrainerCreatedevent with the parametertrainerName.