Skip to content

Commit

Permalink
refactor: return when URD has no permission for UP
Browse files Browse the repository at this point in the history
  • Loading branch information
b00ste committed Aug 14, 2023
1 parent 3d9d893 commit c55e68a
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 139 deletions.
75 changes: 31 additions & 44 deletions contracts/LSP10ReceivedVaults/LSP10Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,6 @@ import {LSP2Utils} from "../LSP2ERC725YJSONSchema/LSP2Utils.sol";
import "../LSP10ReceivedVaults/LSP10Constants.sol";
import "../LSP9Vault/LSP9Constants.sol";

/**
* @dev Reverts when the value stored under the 'LSP10ReceivedVaults[]' Array data key is not valid.
* The value stored under this data key should be exactly 16 bytes long.
*
* Only possible valid values are:
* - any valid uint128 values
* _e.g: `0x00000000000000000000000000000000` (zero), meaning empty array, no vaults received._
* _e.g: `0x00000000000000000000000000000005` (non-zero), meaning 5 array elements, 5 vaults received._
*
* - `0x` (nothing stored under this data key, equivalent to empty array).
*
* @param invalidValueStored The invalid value stored under the `LSP10ReceivedVaults[]` Array data key.
* @param invalidValueLength The invalid number of bytes stored under the `LSP10ReceivedVaults[]` Array data key (MUST be 16 bytes long).
*/
error InvalidLSP10ReceivedVaultsArrayLength(
bytes invalidValueStored,
uint256 invalidValueLength
);

/**
* @dev Reverts when the `LSP10Vaults[]` Array reaches its maximum limit (`max(uint128)`).
* @param notRegisteredVault The address of the LSP9Vault that could not be registered.
*/
error MaxLSP10VaultsCountReached(address notRegisteredVault);

/**
* @dev Reverts when the vault index is superior to `max(uint128)`.
* @param index The vault index.
*/
error VaultIndexSuperiorToUint128(uint256 index);

/**
* @title LSP10 Utility library.
* @author Yamen Merhi <YamenMerhi>, Jean Cavallera <CJ42>
Expand All @@ -68,7 +37,15 @@ library LSP10Utils {
address receiver,
address vault,
bytes32 vaultMapKey
) internal view returns (bytes32[] memory keys, bytes[] memory values) {
)
internal
view
returns (
bytes32[] memory keys,
bytes[] memory values,
bytes memory errorMsg
)
{
keys = new bytes32[](3);
values = new bytes[](3);

Expand All @@ -78,16 +55,17 @@ library LSP10Utils {
// CHECK it's either the first vault received,
// or the storage is already set with a valid `uint128` value
if (encodedArrayLength.length != 0 && encodedArrayLength.length != 16) {
revert InvalidLSP10ReceivedVaultsArrayLength({
invalidValueStored: encodedArrayLength,
invalidValueLength: encodedArrayLength.length
});
return (
keys,
values,
"LSP10: Invalid received vaults array length"
);
}

uint128 oldArrayLength = uint128(bytes16(encodedArrayLength));

if (oldArrayLength == type(uint128).max) {
revert MaxLSP10VaultsCountReached({notRegisteredVault: vault});
return (keys, values, "LSP10: Max vaults count reached");
}

uint128 newArrayLength = oldArrayLength + 1;
Expand Down Expand Up @@ -125,24 +103,33 @@ library LSP10Utils {
address sender,
bytes32 vaultMapKey,
uint128 vaultIndex
) internal view returns (bytes32[] memory keys, bytes[] memory values) {
)
internal
view
returns (
bytes32[] memory keys,
bytes[] memory values,
bytes memory errorMsg
)
{
IERC725Y account = IERC725Y(sender);
bytes memory lsp10VaultsCountValue = getLSP10ReceivedVaultsCount(
account
);

if (lsp10VaultsCountValue.length != 16) {
revert InvalidLSP10ReceivedVaultsArrayLength({
invalidValueStored: lsp10VaultsCountValue,
invalidValueLength: lsp10VaultsCountValue.length
});
return (
keys,
values,
"LSP10: Invalid received vaults array length"
);
}

// Updating the number of the received vaults
uint128 oldArrayLength = uint128(bytes16(lsp10VaultsCountValue));

if (oldArrayLength > type(uint128).max) {
revert VaultIndexSuperiorToUint128(oldArrayLength);
return (keys, values, "LSP10: Vault index superior to uint128");
}

// Updating the number of the received vaults (decrementing by 1
Expand Down Expand Up @@ -235,7 +222,7 @@ library LSP10Utils {
values[4] = bytes.concat(_INTERFACEID_LSP9, bytes16(vaultIndex));
} else {
// If index is bigger than the array length, out of bounds
return (keys, values);
return (keys, values, "LSP10: Out of bounds");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ contract LSP1UniversalReceiverDelegateUP is ERC165, ILSP1UniversalReceiver {
// The notifier is supposed to be either the LSP7 or LSP8 or LSP9 contract
// If it's EOA we revert to avoid registering the EOA as asset or vault (spam protection)
// solhint-disable avoid-tx-origin
if (notifier == tx.origin) revert CannotRegisterEOAsAsAssets(notifier);
if (notifier == tx.origin)
return "LSP1: Cannot register EOAs as assets";

// Generate the LSP5ReceivedAssetsMap/LSP10VaultsMap based on the prefix and the notifier
bytes32 notifierMapKey = LSP2Utils.generateMappingKey(
Expand Down Expand Up @@ -141,7 +142,7 @@ contract LSP1UniversalReceiverDelegateUP is ERC165, ILSP1UniversalReceiver {
address notifier,
bytes32 notifierMapKey,
bytes4 interfaceID
) internal virtual returns (bytes memory) {
) internal virtual returns (bytes memory errorMsg) {
bytes32[] memory dataKeys;
bytes[] memory dataValues;

Expand All @@ -157,26 +158,66 @@ contract LSP1UniversalReceiverDelegateUP is ERC165, ILSP1UniversalReceiver {
if (balance == 0) return "LSP1: balance not updated";
}

(dataKeys, dataValues) = LSP5Utils.generateReceivedAssetKeys(
msg.sender,
notifier,
notifierMapKey,
interfaceID
);
(dataKeys, dataValues, errorMsg) = LSP5Utils
.generateReceivedAssetKeys(
msg.sender,
notifier,
notifierMapKey,
interfaceID
);

/**
* `generateReceivedAssetKeys(...)` returns empty arrays when encountering errors
*/
if (
(dataKeys.length == 0 && dataValues.length == 0) ||
errorMsg.length > 0
) return errorMsg;

// Set the LSP5 generated data keys on the account
IERC725Y(msg.sender).setDataBatch(dataKeys, dataValues);
return "";
} else {
(dataKeys, dataValues) = LSP10Utils.generateReceivedVaultKeys(
msg.sender,
notifier,
notifierMapKey
(bool success, bytes memory returnedData) = msg.sender.call(
abi.encodeWithSelector(
IERC725Y.setDataBatch.selector,
dataKeys,
dataValues
)
);

if (success) {
return "";
} else {
return returnedData;
}
} else {
(dataKeys, dataValues, errorMsg) = LSP10Utils
.generateReceivedVaultKeys(
msg.sender,
notifier,
notifierMapKey
);

/**
* `generateReceivedVaultKeys(...)` returns empty arrays when encountering errors
*/
if (
(dataKeys.length == 0 && dataValues.length == 0) ||
errorMsg.length > 0
) return errorMsg;

// Set the LSP10 generated data keys on the account
IERC725Y(msg.sender).setDataBatch(dataKeys, dataValues);
return "";
(bool success, bytes memory returnedData) = msg.sender.call(
abi.encodeWithSelector(
IERC725Y.setDataBatch.selector,
dataKeys,
dataValues
)
);

if (success) {
return "";
} else {
return returnedData;
}
}
}

Expand All @@ -190,7 +231,7 @@ contract LSP1UniversalReceiverDelegateUP is ERC165, ILSP1UniversalReceiver {
address notifier,
bytes32 notifierMapKey,
uint128 arrayIndex
) internal virtual returns (bytes memory) {
) internal virtual returns (bytes memory errorMsg) {
bytes32[] memory dataKeys;
bytes[] memory dataValues;

Expand All @@ -200,41 +241,63 @@ contract LSP1UniversalReceiverDelegateUP is ERC165, ILSP1UniversalReceiver {
uint256 balance = ILSP7DigitalAsset(notifier).balanceOf(msg.sender);
if (balance != 0) return "LSP1: full balance is not sent";

(dataKeys, dataValues) = LSP5Utils.generateSentAssetKeys(
(dataKeys, dataValues, errorMsg) = LSP5Utils.generateSentAssetKeys(
msg.sender,
notifierMapKey,
arrayIndex
);

/**
* `generateSentAssetKeys(...)` returns empty arrays in the following cases:
* - the index returned from the data key `notifierMapKey` is bigger than
* the length of the `LSP5ReceivedAssets[]`, meaning, index is out of bounds.
* `generateSentAssetKeys(...)` returns empty arrays when encountering errors
*/
if (dataKeys.length == 0 && dataValues.length == 0)
return "LSP1: asset data corrupted";
if (
(dataKeys.length == 0 && dataValues.length == 0) ||
errorMsg.length > 0
) return errorMsg;

// Set the LSP5 generated data keys on the account
IERC725Y(msg.sender).setDataBatch(dataKeys, dataValues);
return "";
(bool success, bytes memory returnedData) = msg.sender.call(
abi.encodeWithSelector(
IERC725Y.setDataBatch.selector,
dataKeys,
dataValues
)
);

if (success) {
return "";
} else {
return returnedData;
}
} else {
(dataKeys, dataValues) = LSP10Utils.generateSentVaultKeys(
(dataKeys, dataValues, errorMsg) = LSP10Utils.generateSentVaultKeys(
msg.sender,
notifierMapKey,
arrayIndex
);

/**
* `generateSentAssetKeys(...)` returns empty arrays in the following cases:
* - the index returned from the data key `notifierMapKey` is bigger than
* the length of the `LSP10Vaults[]`, meaning, index is out of bounds.
* `generateSentVaultKeys(...)` returns empty arrays when encountering errors
*/
if (dataKeys.length == 0 && dataValues.length == 0)
return "LSP1: asset data corrupted";
if (
(dataKeys.length == 0 && dataValues.length == 0) ||
errorMsg.length > 0
) return errorMsg;

// Set the LSP10 generated data keys on the account
IERC725Y(msg.sender).setDataBatch(dataKeys, dataValues);
return "";
(bool success, bytes memory returnedData) = msg.sender.call(
abi.encodeWithSelector(
IERC725Y.setDataBatch.selector,
dataKeys,
dataValues
)
);

if (success) {
return "";
} else {
return returnedData;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ contract LSP1UniversalReceiverDelegateVault is ERC165, ILSP1UniversalReceiver {
* @custom:requirements Cannot accept native tokens.
*
* @param typeId Unique identifier for a specific notification.
* @return result The result of the reaction for `typeId`.
* @return errorMsg The result of the reaction for `typeId`.
*/
function universalReceiver(
bytes32 typeId,
bytes memory /* data */
) public payable virtual returns (bytes memory result) {
) public payable virtual returns (bytes memory errorMsg) {
if (msg.value != 0) revert NativeTokensNotAccepted();
// This contract acts like a UniversalReceiverDelegate of a Vault where we append the
// address and the value, sent to the universalReceiver function of the LSP9, to the msg.data
Expand All @@ -68,7 +68,8 @@ contract LSP1UniversalReceiverDelegateVault is ERC165, ILSP1UniversalReceiver {
return "LSP1: typeId out of scope";

// solhint-disable avoid-tx-origin
if (notifier == tx.origin) revert CannotRegisterEOAsAsAssets(notifier);
if (notifier == tx.origin)
return "LSP1: Cannot register EOAs as assets";

bytes32 notifierMapKey = LSP2Utils.generateMappingKey(
mapPrefix,
Expand Down Expand Up @@ -96,12 +97,21 @@ contract LSP1UniversalReceiverDelegateVault is ERC165, ILSP1UniversalReceiver {
if (balance == 0) return "LSP1: balance not updated";
}

(dataKeys, dataValues) = LSP5Utils.generateReceivedAssetKeys(
msg.sender,
notifier,
notifierMapKey,
interfaceID
);
(dataKeys, dataValues, errorMsg) = LSP5Utils
.generateReceivedAssetKeys(
msg.sender,
notifier,
notifierMapKey,
interfaceID
);

/**
* `generateReceivedAssetKeys(...)` returns empty arrays when encuntering errors
*/
if (
(dataKeys.length == 0 && dataValues.length == 0) ||
errorMsg.length > 0
) return errorMsg;

IERC725Y(msg.sender).setDataBatch(dataKeys, dataValues);
} else {
Expand All @@ -123,7 +133,7 @@ contract LSP1UniversalReceiverDelegateVault is ERC165, ILSP1UniversalReceiver {
// fetched under the LSP5ReceivedAssetsMap/LSP10VaultsMap data key
uint128 assetIndex = uint128(uint160(bytes20(notifierMapValue)));

(dataKeys, dataValues) = LSP5Utils.generateSentAssetKeys(
(dataKeys, dataValues, errorMsg) = LSP5Utils.generateSentAssetKeys(
msg.sender,
notifierMapKey,
assetIndex
Expand All @@ -134,8 +144,10 @@ contract LSP1UniversalReceiverDelegateVault is ERC165, ILSP1UniversalReceiver {
* - the index returned from the data key `notifierMapKey` is bigger than
* the length of the `LSP5ReceivedAssets[]`, meaning, index is out of bounds.
*/
if (dataKeys.length == 0 && dataValues.length == 0)
return "LSP1: asset data corrupted";
if (
(dataKeys.length == 0 && dataValues.length == 0) ||
errorMsg.length > 0
) return errorMsg;

IERC725Y(msg.sender).setDataBatch(dataKeys, dataValues);
}
Expand Down
Loading

0 comments on commit c55e68a

Please sign in to comment.