# @erc725/smart-contracts 4.2.0 ## ERC725Y - Mark `setData(..)` functions as payable: ```js= // Single function setData(bytes32 dataKey, bytes memory dataValue) external payable // Array function setData(bytes32[] memory dataKeys, bytes[] memory dataValues) external payable; ``` This change was added to allow implementations that extend the ERC725Y contract to allow receiving value while setting data. The implementation of ERC725Y contract reverts with a solidity custom error when sending value. ```js= error ERC725Y_MsgValueDisallowed(); ``` People wishing to disallow sending value to setData can follow the same approach. ### For Contracts that Inherits setData All the contracts that override `setData(..)` functions needs to explicitly mark the function as payable again, as solidity does not allow going from payable - to non payable, and vice versa. # @lukso/lsp-smart-contracts 0.9.0 ## LSP0 - Change in interfaceId from `0x66767497` to `0x0f15a0af` <hr> - Add batchCalls function: ```soldity= function batchCalls(bytes[] calldata data) external returns (bytes[] memory results); ``` Check the specification for the function in the LIP. This function is useful to batch calls to different LSP0 functions, for example, if the account was owned by an EOA before it was not possible to batch setData and execute calls, now it's possible: ```javascript= let setDataPayload = context.universalProfile.interface .encodeFunctionData("setData(bytes32,bytes)",[key, value]); let executePayload = context.universalProfile.interface .encodeFunctionData( "execute(uint256,address,uint256,bytes)", [Operation_Call, recipient, amountToSend, dataToSend] ); await context.universalProfile.connect(context.owner) .batchCalls([setDataPayload, executePayload]) ``` <hr> - LSP0 now supports the `LSP20-CallVerification` Standard, where if the LSP0 contract is owned by a contract, and this contract (owner) supports the LSP20 as well, the interaction can happen directly with the LSP0 itself, and the verification happens internally by LSP0 calling its owner to verify that the call should pass according to the owner. Check LSP20-CallVerification LIP Spec for more information. #### What has been changed - Calls by the owner of the LSP0 didn't change. - Calls by other addresses to the LSP0 before was reverting with "Ownable: Caller is not the owner", now it will pass if the caller is allowed by the owner of LSP0 (each owner can have different logic), if the caller is not allowed it will revert with either `LSP20CallingVerifierFailed(bool)` or `LSP20InvalidMagicValue(bool,bytes)` indicating that the owner didn't return the magicValue meaning he is not allowed to Call LSP0 functions. ## LSP2 - Change the value to store in the array keyType from `uint256` to `uint128`. - Before: example: Length 1 `0x0000000000000000000000000000000000000000000000000000000000000001` - Now: example: Length 1 `0x00000000000000000000000000000001` ## LSP6 - New format for AllowedCalls Before: ```json= { "name": "AddressPermissions:AllowedCalls:<address>", "key": "0x4b80742de2bf393a64c70000<address>", "keyType": "MappingWithGrouping", "valueType": "(bytes4,address,bytes4)[CompactBytesArray]", "valueContent": "(Bytes4,Address,Bytes4)" } ``` Now: ```json= { "name": "AddressPermissions:AllowedCalls:<address>", "key": "0x4b80742de2bf393a64c70000<address>", "keyType": "MappingWithGrouping", "valueType": "(bytes4,address,bytes4,bytes4)[CompactBytesArray]", "valueContent": "(BitArray,Address,Bytes4,Bytes4)" } ``` Before the list of Allowed Calls was used as a generic list of whitelisted standards/addresses/functions. But this list applies to all the permissions related to contract interaction (TRANSFERVALUE, CALL, STATICCALL and DELEGATECALL). Therefore, this list acts like a generic “umbrella” for the 4 permissions above. Meaning if you set as AllowedCalls for the controller X the address A, the function F, and the standard S, it means the controller X can only TransferValue or Call or StaticCall to these restrictions. But you cannot put restrictions for a controller to allow him to Call address B but not StaticCall to it. New behavior was added so that restrictions can be bounded to certain actions: For each allowed call in the list, we also define using a bitArray what the controller can do: - staticcall? (call `read` only functions) - send value? (`value`) - call (`write` data to the contract state or the blockchain) - delegatecall(`execute` functionalities (= functions) in the context of the current contract) What action can a controller do will be defined by a bytes4 bitArray where: ```json= VALUE: "0x00000001", CALL: "0x00000002", STATICCALL: "0x00000004", DELEGATECALL: "0x00000008", ``` **Example 1:** If controller A has [CALL](#permissions) permission, and have the following value for AllowedCalls: ``` 0x002000000002cafecafecafecafecafecafecafecafecafecafe11223344bb11bb11 ``` `0x0020` is the length of the AllowedCalls. The `restrictionOperations` is **`0x00000002`**, meaning that the restrictions above only applies when the operation **[CALL](https://github.com/ERC725Alliance/ERC725/blob/develop/docs/ERC-725.md#execute)** is being executed. The controller A is allowed to interact via the **CALL** operation with the function selector **`0xbb11bb11`** on the **`0xcafecafecafecafecafecafecafecafecafecafe`** address as long as the address supports **`0x11223344`** interfaceId through [ERC165]. **Example 2:** If controller B has [TRANSFERVALUE](#permissions) and [CALL](#permissions) permissions, and have the following value for AllowedCalls: ``` 0x002000000003cafecafecafecafecafecafecafecafecafecafe11223344bb11bb11 ``` The `callRestrictions` is **`0x00000003`**, it means that the restrictions above applies when the operation **[CALL](https://github.com/ERC725Alliance/ERC725/blob/develop/docs/ERC-725.md#execute)** or **[TRANSFERVALUE](https://github.com/ERC725Alliance/ERC725/blob/develop/docs/ERC-725.md#execute)** is being executed. The controller B is allowed to **CALL** or **TransferValue** to: - the contract deployed at address **`0xcafecafecafecafecafecafecafecafecafecafe`** as long as this contract supports the interfaceId **`0x11223344`** through [ERC165]. - only the function with selector **`0xbb11bb11`** on this contract. - this function on this contract with or without transferring value at the same time (because of the additional **TransferValue** in the `callRestrictions`). **Example 3:** If controller B has [DELEGATECALL](#permissions) permission, and have the following value for AllowedCalls: ``` 0x002000000002cafecafecafecafecafecafecafecafecafecafe11223344bb11bb11 ``` The `restrictionOperations` is **`0x00000002`**, it means that the restrictions above only applies when the operation **[CALL](https://github.com/ERC725Alliance/ERC725/blob/develop/docs/ERC-725.md#execute)** is being executed. Given that the controller B have the **DELEGATECALL** Permission and the restrictions only applies for the **CALL** operation, any execution of **DELEGATECALL** operation will fail even to the function **`0xbb11bb11`** on **`0xcafecafecafecafecafecafecafecafecafecafe`** address. **Example 4:** If controller B has [TRANSFERVALUE](#permissions) and [CALL](#permissions) permissions, and have the following value for AllowedCalls: ``` 0x002000000001cafecafecafecafecafecafecafecafecafecafe11223344bb11bb11002000000002ffffffffffffffffffffffffffffffffffffffff68686868ffffffff ``` Each element of the compact bytes array have a different `restrictionOperations`: - **`0x000000001`** for the first element allowing the controller B to only **TransferValue** to the function **`0xbb11bb11`** on **`0xcafecafecafecafecafecafecafecafecafecafe`** address as long as the address supports **`0x11223344`** interfaceId through [ERC165]. - **`0x000000002`** for the second element allowing the controller B to only **Call** any function on any contract that support the interface ID **`0x68686868`** through [ERC165]. <hr> - Change event in LSP6: - From: `Executed(bytes4 selector, uint256 value)` - To: `VerifiedCall(address signer, uint256 value, bytes4 selector)` <hr> - For controllers that have the `DEPLOY` permission, and wishing to fund the contract being deployed through the LPS6-ERC725Account: - Before: Permission needed was `DEPLOY` and `TRANSFERVALUE` (Restrictions of TRANSFERVALUE (AllowedCalls) didn't apply to `DEPLOY` permission ) - Now: Permission needed is `DEPLOY` and `SUPER_TRANSFERVALUE` <hr> - Change `CHANGEPERMISSIONS` to `EDITPERMISSIONS` <hr> - Change the value to store in the `AddressPermissions[]` array from `uint256` to `uint128`. - Before: example: Length 1 `0x0000000000000000000000000000000000000000000000000000000000000001` - Now: example: Length 1 `0x00000000000000000000000000000001` ## LSP5 - Change the value to store in the `LSP5ReceivedAssets[]` array from `uint256` to `uint128`. - Before: example: Length 1 `0x0000000000000000000000000000000000000000000000000000000000000001` - Now: example: Length 1 `0x00000000000000000000000000000001` <hr> - Change the value to store in the `LSP5ReceivedAssetsMap:<address>` from `(bytes4,uint64)` to `(bytes4,uint128)`. - Before: `0xaabbccdd0000000000000001` - Now: `0xaabbccdd00000000000000000000000000000001` ## LSP10 - Change the value to store in the `LSP10Vaults[]` array from `uint256` to `uint128`. - Before: example: Length 1 `0x0000000000000000000000000000000000000000000000000000000000000001` - Now: example: Length 1 `0x00000000000000000000000000000001` <hr> - Change the value to store in the `LSP10VaultsMap:<address>` from `(bytes4,uint64)` to `(bytes4,uint128)`. - Before: `0xaabbccdd0000000000000001` - Now: `0xaabbccdd00000000000000000000000000000001` ## LSP9 - Change in interfaceId from `0x7050cee9` to `0x19331ad1` <hr> - Add batchCalls function: ```soldity= function batchCalls(bytes[] calldata data) external returns (bytes[] memory results); ``` Check the specification for the function in the LIP. Same example as above, the only difference is that a vault is usually owned by a UniversalProfile, so the batchCalls should be encoded and called by the execute function of the UniversalProfile. ## LSP16 - Mark `generateSalt(..)` function as public to allow easy access to the salt that will be used to create the contract. ```js= function generateSalt(bool initializable, bytes memory initializeCallData, bytes32 providedSalt) public pure virtual returns (bytes32); ```