This is a tool for generating custom Tenderly devnet configs, by modifying the network state (smart contract storages), in order to make ourselves owners of some tokens.
Live Site: https://devnet-config.onrender.com/
CRYPTOKITTIES
In this example we are going to make ourselves owners of the 1359295 Cryptokitty NFT and import the token into our MetaMask wallet.
kittyIndexToOwner
- Get the contract address
- The Cryptokitties contract address is
0x06012c8cf97BEaD5deAe237070F9587f8E7A266d
- The Cryptokitties contract address is
- Get the contract code from Etherscan
- Identify which variable you want to change. In our case, we want to change the mapping where the token owners are set, so it is the
mapping(uint256=> address)
- Identify which variable you want to change. In our case, we want to change the mapping where the token owners are set, so it is the
- Get the storage layout. I use sol2uml tool
sol2uml storage ./Cryptokitties.sol -c KittyCore

- Get the storage address
- The key is the token id we choose the
tokenId1359295we need to convert it to hex and left pad this to a 32 bytes value (it’s already a 32 bytes value)0x000000000000000000000000000000000000000000000000000000000014BDBF - The mapping is declared at storage slot position 7, padded to 32 bytes would be
0x0000000000000000000000000000000000000000000000000000000000000007 - Concatenating the 2 values we get
0x000000000000000000000000000000000000000000000000000000000014bdbf0000000000000000000000000000000000000000000000000000000000000007 - Calculate the keccak256 (notice we should pass the value in lower case and input type hex). You can calculate it here
- The resulting slot is
0xd9fbdcbb8ce2d4417e6ad68850ec200e7d37b49be27a4bff9848b9f2d04aa79a
- The key is the token id we choose the
- Set the value you want
- In this case we pass our address, again padded to 32 bytes
0x0000000000000000000000007Be9763a718C0539017E2Ab6fC42853b4aEeb6B
- In this case we pass our address, again padded to 32 bytes
Create the Config File
Now we can create the Tenderly config YAML file. We can copy the default template and add our changes regarding the punk contract.
Here is the result. I’ve also included some ERC20 and ETH balance to my account too.
Validate results with eth_getStorageAt request
Now we are going to validate that the sotrage has been correctly modified by using the eth_getStorageAt method on the Tenderly RPC we just setup
- POST request with the following JSON body. Notice we cannot point directly to the slot, as it’s a
mappingvariable
{
"jsonrpc":"2.0",
"method":"eth_getStorageAt",
"params":[
"0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb", // contract address
"0xbbc70db1b6c7afd11e79c0fb0051300458f1a3acb8ee9789d9b6b26c61ad9bc7", // storage address
"latest"
],
"id":1
}
- We get the following response, with our address as the owner of the NFT with id 1
{
"id": 1,
"jsonrpc": "2.0",
"result": "0x00000000000000000000000007be9763a718c0539017e2ab6fc42853b4aeeb6b"
}
- Now we can also make a call for checking the reverse. We pass our address to get our tokens. In this case the request is:
{
"jsonrpc":"2.0",
"method":"eth_getStorageAt",
"params":[
"0xb47e3cd837ddf8e4c57f05d70ab865de6e193bbb", // 436
"0x65ca9b454c6468268ab14e3b8f391b420b731f3aa9ac0f4a1eb0a190aaebdcbe",
"latest"
],
"id":1
}
- And we get the following response
{
"id": 1,
"jsonrpc": "2.0",
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
You can check that if you change the endpoint to Infura, the results are displaying the real owner of the asset.
