---
# System prepended metadata

title: Untitled

---

### Notes

-   El Wrapper en la funcion registerNewType el primero es el index 1.

```solidity
function _registerNewType(address propertyManager_, bool isFungible_) internal {
    require(propertyManager_ != address(0), "Cannot set zero address");

    typesCount++;

    typeContractPm[typesCount] = IExternalTokenPropertyManager(propertyManager_);
    isFungible[typesCount] = isFungible_;
}

```

-   Para ejecutar el wrap() tenes que hacer como usuario un approve al ExternalERC20|721 PM

```typescript
await ERC20Token.connect(users[0]).approve(External_ERC20PropertyManager.address, amount);
```

-   El tema del registerNewType es definitvamente una cagada y estaria bueno cambiarlo porque ademas no tiene condicion de revert en el caso de que vuelvas a agregar el mismo type, te lo pisa y listo. Deberia manejarse por un lado con un enumerable y a su vez la informacion arbitraria de que el tipo 1 es ERC20 , tipo 2 ERC721 ..etc tiene que estar a mi entender dentro del storage del contrato. Si les parece bien a mi me gustaria sugerirselo a Quentin o Pavel en el canal que tenemos.

---

-   La funcion wrap lo primero que hace es consultar si tiene que darle un mNFT al usuario:

```solidity
function _wrap(WrapData memory data) internal {
    if (data.existingMetaNftToUse == 0) {
        metaNftId = metaNft.mint(msg.sender);
    }
}

```

Si vamos a la funcion mint del metaToken es una funcion con permiso tambien:

```solidity
function mint(address account) external onlyMinter returns (uint256) {
    require(MetaTokenStorage.layout().totalClaimed(account) == 0, "Token already minted");
    uint256 pid = _mintInternal(account);
    MetaTokenStorage.layout().setClaimed(account, pid);
    return pid;
}

```

-   Con lo cual el metaNFT tiene que brindar permiso al wrapper para que pueda hacer minter, esto tambien se hace en los tests:

```
            // Adding the Wrapper as minter for MetaNFT
            await metaContracts.PropertyRegistry.grantMinter(Wrapper.address);
```

-   Manejo de los external para con el metaNFT y porque NO es necesario agregar el o los externals al metaNFT:

```solidity
function lockTokensOnMetaNft(LockTokensOnMetaNftData memory data) external onlyWrapper {
    if (!isProperty[property]) {
        bytes32[] memory properties = new bytes32[](1);
        properties[0] = property;

        IMetaPropertyRegistry(propertyRegistry).addCategoryProperty(category, properties);
        isProperty[property] = true;
    }
}

```

-   Como se puede ver invocan al registry para añadir una category y la correspondiente property. Si vamos al registry para ver esa funcion:

```solidity
function addCategoryProperty(bytes32 category, bytes32[] calldata properties) external onlyCategoryManager(category) {
    for (uint256 i = 0; i < properties.length; i++) {
        require(propertiesToCategories[properties[i]] == bytes32(0), "Property already registered");
        propertiesToCategories[properties[i]] = category;
        categories[category].properties.push(properties[i]);
    }
}

```

-   El registry agrega una property a una categoria existente y para eso tiene que asignar al pm como admin de esa categoria. Esto lo realiza aca en los tests lo podemos ver:

```
            // Create category (with the PM as his manager)
            await metaContracts.PropertyRegistry.connect(deployer).addCategory(
                kecakk256("ExternalErc20PropertyManager"),
                false,
                [kecakk256("ERC20")],
                External_ERC20PropertyManager.address
            );
            await metaContracts.PropertyRegistry.connect(deployer).addCategory(
                kecakk256("ExternalErc721PropertyManager"),
                false,
                [kecakk256("ERC721")],
                External_ERC721PropertyManager.address
            );
            await metaContracts.PropertyRegistry.connect(deployer).addCategory(
                kecakk256("ExternalErc1155PropertyManager"),
                false,
                [kecakk256("ERC1155")],
                External_ERC1155PropertyManager.address
            );
```

-   Por ultimo, el PM añade a traves del mNFT una restriccion que es justamente la data asociada al wrap y el timestamp que es lo mas importante que es el periodo de lockeo. El check en el unwrap esta dado por una facet del diamon que son ERC20LockRestriction y ERC1155LockRestriction que añaden hooks al proceso de wrap/unwrap lock/unlock:

```solidity
/**
 * @dev Called by MetaRestrictionsInternal.removeRestrictionInternal()
 * If this is called not from the diamond via delegatecall, address(this) will be the Restriction contract itself which stores no tokens.
 */
function ERC20LockRestriction_removeRestrictionHook(
    uint256, /*pid*/
    bytes32, /*prop*/
    bytes32 rtype,
    bytes memory data
) external onlyDelegatecall {
    require(rtype == RTYPE, "wrong rtype");
    Data memory d = abi.decode(data, (Data));
    require(d.release <= block.timestamp, "Token release time not passed");

    IERC20(d.token).safeTransfer(msg.sender, d.amount);
}

```
