Skip to content

Commit

Permalink
Merge branch 'develop' into DEV-3725
Browse files Browse the repository at this point in the history
  • Loading branch information
CJ42 committed Sep 27, 2023
2 parents 3a1e025 + e6fb55d commit a69fe4a
Show file tree
Hide file tree
Showing 48 changed files with 1,156 additions and 451 deletions.
65 changes: 38 additions & 27 deletions contracts/LSP0ERC725Account/LSP0ERC725AccountCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
_TYPEID_LSP0_OwnershipTransferStarted,
_TYPEID_LSP0_OwnershipTransferred_SenderNotification,
_TYPEID_LSP0_OwnershipTransferred_RecipientNotification
} from "../LSP0ERC725Account/LSP0Constants.sol";
} from "./LSP0Constants.sol";
import {
_INTERFACEID_LSP1,
_LSP1_UNIVERSAL_RECEIVER_DELEGATE_PREFIX,
Expand All @@ -56,7 +56,8 @@ import {

// errors
import {
ERC725Y_DataKeysValuesLengthMismatch
ERC725Y_DataKeysValuesLengthMismatch,
ERC725Y_DataKeysValuesEmptyArray
} from "@erc725/smart-contracts/contracts/errors.sol";
import {
NoExtensionFoundForFunctionSelector
Expand Down Expand Up @@ -146,7 +147,7 @@ abstract contract LSP0ERC725AccountCore is

if (!success) {
// Look for revert reason and bubble it up if present
if (result.length > 0) {
if (result.length != 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable no-inline-assembly
/// @solidity memory-safe-assembly
Expand Down Expand Up @@ -191,16 +192,16 @@ abstract contract LSP0ERC725AccountCore is
emit ValueReceived(msg.sender, msg.value);
}

address _owner = owner();
address accountOwner = owner();

// If the caller is the owner perform execute directly
if (msg.sender == _owner) {
if (msg.sender == accountOwner) {
return ERC725XCore._execute(operationType, target, value, data);
}

// If the caller is not the owner, call {lsp20VerifyCall} on the owner
// Depending on the magicValue returned, a second call is done after execution
bool verifyAfter = LSP20CallVerification._verifyCall(_owner);
bool verifyAfter = LSP20CallVerification._verifyCall(accountOwner);

// Perform the execution
bytes memory result = ERC725XCore._execute(
Expand All @@ -212,7 +213,10 @@ abstract contract LSP0ERC725AccountCore is

// if verifyAfter is true, Call {lsp20VerifyCallResult} on the owner
if (verifyAfter) {
LSP20CallVerification._verifyCallResult(_owner, abi.encode(result));
LSP20CallVerification._verifyCallResult(
accountOwner,
abi.encode(result)
);
}

return result;
Expand All @@ -228,6 +232,9 @@ abstract contract LSP0ERC725AccountCore is
* - If the operation type is `CREATE` (1) or `CREATE2` (2), `target` must be `address(0)`.
* - If the operation type is `STATICCALL` (3) or `DELEGATECALL` (4), `value` transfer is disallowed and must be 0.
*
* @custom:warning
* - The `msg.value` should not be trusted for any method called within the batch with `operationType`: `DELEGATECALL` (4).
*
* @custom:events
* - {Executed} event for each call that uses under `operationType`: `CALL` (0), `STATICCALL` (3) and `DELEGATECALL` (4). (each iteration)
* - {ContractCreated} event, when a contract is created under `operationType`: `CREATE` (1) and `CREATE2` (2) (each iteration)
Expand All @@ -243,10 +250,10 @@ abstract contract LSP0ERC725AccountCore is
emit ValueReceived(msg.sender, msg.value);
}

address _owner = owner();
address accountOwner = owner();

// If the caller is the owner perform execute directly
if (msg.sender == _owner) {
if (msg.sender == accountOwner) {
return
ERC725XCore._executeBatch(
operationsType,
Expand All @@ -258,7 +265,7 @@ abstract contract LSP0ERC725AccountCore is

// If the caller is not the owner, call {lsp20VerifyCall} on the owner
// Depending on the magicValue returned, a second call is done after execution
bool verifyAfter = LSP20CallVerification._verifyCall(_owner);
bool verifyAfter = LSP20CallVerification._verifyCall(accountOwner);

// Perform the execution
bytes[] memory results = ERC725XCore._executeBatch(
Expand All @@ -271,7 +278,7 @@ abstract contract LSP0ERC725AccountCore is
// if verifyAfter is true, Call {lsp20VerifyCallResult} on the owner
if (verifyAfter) {
LSP20CallVerification._verifyCallResult(
_owner,
accountOwner,
abi.encode(results)
);
}
Expand All @@ -296,23 +303,23 @@ abstract contract LSP0ERC725AccountCore is
emit ValueReceived(msg.sender, msg.value);
}

address _owner = owner();
address accountOwner = owner();

// If the caller is the owner perform setData directly
if (msg.sender == _owner) {
if (msg.sender == accountOwner) {
return _setData(dataKey, dataValue);
}

// If the caller is not the owner, call {lsp20VerifyCall} on the owner
// Depending on the magicValue returned, a second call is done after setting data
bool verifyAfter = _verifyCall(_owner);
bool verifyAfter = _verifyCall(accountOwner);

_setData(dataKey, dataValue);

// If verifyAfter is true, Call {lsp20VerifyCallResult} on the owner
// The setData function does not return, second parameter of {_verifyCallResult} will be empty
if (verifyAfter) {
_verifyCallResult(_owner, "");
_verifyCallResult(accountOwner, "");
}
}

Expand All @@ -337,11 +344,15 @@ abstract contract LSP0ERC725AccountCore is
revert ERC725Y_DataKeysValuesLengthMismatch();
}

address _owner = owner();
if (dataKeys.length == 0) {
revert ERC725Y_DataKeysValuesEmptyArray();
}

address accountOwner = owner();

// If the caller is the owner perform setData directly
if (msg.sender == _owner) {
for (uint256 i = 0; i < dataKeys.length; ) {
if (msg.sender == accountOwner) {
for (uint256 i; i < dataKeys.length; ) {
_setData(dataKeys[i], dataValues[i]);

unchecked {
Expand All @@ -354,9 +365,9 @@ abstract contract LSP0ERC725AccountCore is

// If the caller is not the owner, call {lsp20VerifyCall} on the owner
// Depending on the magicValue returned, a second call is done after setting data
bool verifyAfter = _verifyCall(_owner);
bool verifyAfter = _verifyCall(accountOwner);

for (uint256 i = 0; i < dataKeys.length; ) {
for (uint256 i; i < dataKeys.length; ) {
_setData(dataKeys[i], dataValues[i]);

unchecked {
Expand All @@ -367,7 +378,7 @@ abstract contract LSP0ERC725AccountCore is
// If verifyAfter is true, Call {lsp20VerifyCallResult} on the owner
// The setData function does not return, second parameter of {_verifyCallResult} will be empty
if (verifyAfter) {
_verifyCallResult(_owner, "");
_verifyCallResult(accountOwner, "");
}
}

Expand Down Expand Up @@ -572,24 +583,24 @@ abstract contract LSP0ERC725AccountCore is
*
* @custom:requirements Can be only called by the {owner} or by an authorised address that pass the verification check performed on the owner.
*
* @custom:danger Leaves the contract without an owner. Once ownership of the contract has been renounced, any functions that are restricted to be called by the owner will be permanently inaccessible, making these functions not callable anymore and unusable.
* @custom:danger Leaves the contract without an owner. Once ownership of the contract has been renounced, any functions that are restricted to be called by the owner or an address allowed by the owner will be permanently inaccessible, making these functions not callable anymore and unusable.
*
*/
function renounceOwnership()
public
virtual
override(LSP14Ownable2Step, OwnableUnset)
{
address _owner = owner();
address accountOwner = owner();

// If the caller is the owner perform renounceOwnership directly
if (msg.sender == _owner) {
if (msg.sender == accountOwner) {
return LSP14Ownable2Step._renounceOwnership();
}

// If the caller is not the owner, call {lsp20VerifyCall} on the owner
// Depending on the magicValue returned, a second call is done after transferring ownership
bool verifyAfter = _verifyCall(_owner);
bool verifyAfter = _verifyCall(accountOwner);

address previousOwner = owner();
LSP14Ownable2Step._renounceOwnership();
Expand All @@ -604,7 +615,7 @@ abstract contract LSP0ERC725AccountCore is
// If verifyAfter is true, Call {lsp20VerifyCallResult} on the owner
// The transferOwnership function does not return, second parameter of {_verifyCallResult} will be empty
if (verifyAfter) {
_verifyCallResult(_owner, "");
_verifyCallResult(accountOwner, "");
}
}

Expand Down Expand Up @@ -671,7 +682,7 @@ abstract contract LSP0ERC725AccountCore is
address _owner = owner();

// If owner is a contract
if (_owner.code.length > 0) {
if (_owner.code.length != 0) {
(bool success, bytes memory result) = _owner.staticcall(
abi.encodeWithSelector(
IERC1271.isValidSignature.selector,
Expand Down
2 changes: 1 addition & 1 deletion contracts/LSP14Ownable2Step/ILSP14Ownable2Step.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ interface ILSP14Ownable2Step {
* @dev Transfer ownership of the contract from the current {owner()} to the {pendingOwner()}.
*
* Once this function is called:
* - The current {owner()} will loose access to the functions restricted to the {owner()} only.
* - The current {owner()} will lose access to the functions restricted to the {owner()} only.
* - The {pendingOwner()} will gain access to the functions restricted to the {owner()} only.
*
* @notice `msg.sender` is accepting ownership of contract: `address(this)`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ contract LSP1UniversalReceiverDelegateUP is ERC165, ILSP1UniversalReceiver {
) internal returns (bytes memory) {
// CHECK balance only when the Token contract is already deployed,
// not when tokens are being transferred on deployment through the `constructor`
if (notifier.code.length > 0) {
if (notifier.code.length != 0) {
// if the amount sent is 0, then do not update the keys
try ILSP7DigitalAsset(notifier).balanceOf(msg.sender) returns (
uint256 balance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ contract LSP1UniversalReceiverDelegateVault is ERC165, ILSP1UniversalReceiver {
) internal returns (bytes memory) {
// CHECK balance only when the Token contract is already deployed,
// not when tokens are being transferred on deployment through the `constructor`
if (notifier.code.length > 0) {
if (notifier.code.length != 0) {
// if the amount sent is 0, then do not update the keys
try ILSP7DigitalAsset(notifier).balanceOf(msg.sender) returns (
uint256 balance
Expand Down
10 changes: 7 additions & 3 deletions contracts/LSP20CallVerification/LSP20CallVerification.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {ILSP20CallVerifier as ILSP20} from "./ILSP20CallVerifier.sol";
// errors
import {
LSP20InvalidMagicValue,
LSP20CallingVerifierFailed
LSP20CallingVerifierFailed,
LSP20EOACannotVerifyCall
} from "./LSP20Errors.sol";

/**
Expand All @@ -26,6 +27,9 @@ abstract contract LSP20CallVerification {
function _verifyCall(
address logicVerifier
) internal virtual returns (bool verifyAfter) {
if (logicVerifier.code.length == 0)
revert LSP20EOACannotVerifyCall(logicVerifier);

(bool success, bytes memory returnedData) = logicVerifier.call(
abi.encodeWithSelector(
ILSP20.lsp20VerifyCall.selector,
Expand All @@ -42,7 +46,7 @@ abstract contract LSP20CallVerification {
if (bytes3(magicValue) != bytes3(ILSP20.lsp20VerifyCall.selector))
revert LSP20InvalidMagicValue(false, returnedData);

return magicValue[3] == 0x01 ? true : false;
return bytes1(magicValue[3]) == 0x01;
}

/**
Expand Down Expand Up @@ -89,7 +93,7 @@ abstract contract LSP20CallVerification {
bytes memory returnedData
) internal pure virtual {
// Look for revert reason and bubble it up if present
if (returnedData.length > 0) {
if (returnedData.length != 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable no-inline-assembly
/// @solidity memory-safe-assembly
Expand Down
6 changes: 6 additions & 0 deletions contracts/LSP20CallVerification/LSP20Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,9 @@ error LSP20CallingVerifierFailed(bool postCall);
* @param returnedData The data returned by the call to the logic verifier
*/
error LSP20InvalidMagicValue(bool postCall, bytes returnedData);

/**
* @dev Reverts when the logic verifier is an Externally Owned Account (EOA) that cannot return the LSP20 magic value.
* @param logicVerifier The address of the logic verifier
*/
error LSP20EOACannotVerifyCall(address logicVerifier);
3 changes: 1 addition & 2 deletions contracts/LSP25ExecuteRelayCall/LSP25MultiChannelNonce.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ abstract contract LSP25MultiChannelNonce {
address from,
uint128 channelId
) internal view virtual returns (uint256 idx) {
uint256 nonceInChannel = _nonceStore[from][channelId];
return (uint256(channelId) << 128) | nonceInChannel;
return (uint256(channelId) << 128) | _nonceStore[from][channelId];
}

/**
Expand Down
68 changes: 0 additions & 68 deletions contracts/LSP2ERC725YJSONSchema/LSP2Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -308,74 +308,6 @@ library LSP2Utils {
return true;
}

/**
* @dev Verify if `data` is an abi-encoded array of addresses (`address[]`) encoded according to the ABI specs.
*
* @param data The bytes value to verify.
*
* @return `true` if the `data` represents an abi-encoded array of addresses, `false` otherwise.
*/
function isEncodedArrayOfAddresses(
bytes memory data
) internal pure returns (bool) {
if (!isEncodedArray(data)) return false;

uint256 offset = uint256(bytes32(data));
uint256 arrayLength = data.toUint256(offset);

uint256 pointer = offset + 32;

for (uint256 ii = 0; ii < arrayLength; ) {
bytes32 key = data.toBytes32(pointer);

// check that the leading bytes are zero bytes "00"
// NB: address type is padded on the left (unlike bytes20 type that is padded on the right)
if (bytes12(key) != bytes12(0)) return false;

// increment the pointer
pointer += 32;

unchecked {
++ii;
}
}

return true;
}

/**
* @dev Verify if `data` is an abi-array of `bytes4` values (`bytes4[]`) encoded according to the ABI specs.
*
* @param data The bytes value to verify.
*
* @return `true` if the `data` represents an abi-encoded array of `bytes4`, `false` otherwise.
*/
function isBytes4EncodedArray(
bytes memory data
) internal pure returns (bool) {
if (!isEncodedArray(data)) return false;

uint256 offset = uint256(bytes32(data));
uint256 arrayLength = data.toUint256(offset);
uint256 pointer = offset + 32;

for (uint256 ii = 0; ii < arrayLength; ) {
bytes32 key = data.toBytes32(pointer);

// check that the trailing bytes are zero bytes "00"
if (uint224(uint256(key)) != 0) return false;

// increment the pointer
pointer += 32;

unchecked {
++ii;
}
}

return true;
}

/**
* @dev Verify if `data` is a valid array of value encoded as a `CompactBytesArray` according to the LSP2 `CompactBytesArray` valueType specification.
*
Expand Down
Loading

0 comments on commit a69fe4a

Please sign in to comment.