# Smart contract

## The mirror structure (web3 link)

The 1st way to implement the wallet mirror is to create a direct link between the user's address and that of the wallet mirror. This is the most efficient way, as it enables the user to interact with the smart-contract using his wallet. As a result, it is perhaps less efficient than web2 integration for onboarding.

To implement this technique, you'll need

* A structure with the information you need for your dApp,
* A mapping linking the address to the structure,
* A reversed mapping to force the transaction to be sent via the mirror.

### Structure example:

```solidity
    /// @notice User storage structure
    struct User {
            /// @notice mirror address used to sign txns
        address internalAddress;
        
    // additional extra data can be stored too
            /// @notice example counter for games played by this user
        uint gamesPlayed;
            /// @notice amount of token loaded inside the game contract
        uint tokenAvailable;
    }
```

### Mapping examples:

```solidity
    /// @notice Real Player Wallet -> Player Data
    mapping(address => Player) public players;

    /// @notice Internal Wallet -> Real Player Wallet
    mapping(address => address) public playersReversed;
```

### Modifier example:

<pre class="language-solidity"><code class="lang-solidity"><strong>        address sender = msg.sender;
</strong>        address realPlayer = playersReversed[sender];
</code></pre>

You'll find more details about mapping and modifiers in the [Mapping of addresses](https://jungle-toolkit.gitbook.io/evm-xcm-jungle-toolkit/build-an-evm+substrate-wallet-compatible-architecture-in-your-dapp/mapping-of-addresses) section.

### Registration function example:

```solidity
    /**
     * @notice Necessary to create the mirror wallet
     * @dev Deployer Required
     * @param _playerWallet: real EOA of user
     * @param _internalWallet: walled used to relay txns
    */
    function createPlayer(address _playerWallet, address _internalWallet) public payable onlyOwner {
        require(players[_playerWallet].internalAddress == 0x0000000000000000000000000000000000000000, "Player already exists");
        players[_playerWallet].internalAddress = _internalWallet;
        playersReversed[_internalWallet] = _playerWallet;
    }
```
