Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 41 additions & 11 deletions contracts/Delegatable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {EIP712DOMAIN_TYPEHASH} from "./TypesAndDecoders.sol";
import {Delegation, Invocation, Invocations, SignedInvocation, SignedDelegation} from "./CaveatEnforcer.sol";
import {DelegatableCore} from "./DelegatableCore.sol";
import {IDelegatable} from "./interfaces/IDelegatable.sol";
import {IERC1271Wallet} from "./interfaces/IERC1271Wallet.sol";

abstract contract Delegatable is IDelegatable, DelegatableCore {
/// @notice The hash of the domain separator used in the EIP712 domain hash.
Expand Down Expand Up @@ -77,37 +78,66 @@ abstract contract Delegatable is IDelegatable, DelegatableCore {
return keccak256(encoded);
}

function verifyDelegationSignature(SignedDelegation memory signedDelegation)
function verifyDelegationSignature(
SignedDelegation calldata signedDelegation
)
public
view
virtual
override(IDelegatable, DelegatableCore)
returns (address)
{
Delegation memory delegation = signedDelegation.delegation;
Delegation calldata delegation = signedDelegation.delegation;
bytes32 sigHash = getDelegationTypedDataHash(delegation);
address recoveredSignatureSigner = recover(
address recoveredSignatureSigner = flexibleRecover(
sigHash,
signedDelegation.signature
signedDelegation.signature,
signedDelegation.signerIsContract
);
return recoveredSignatureSigner;
}

function verifyInvocationSignature(SignedInvocation memory signedInvocation)
public
view
returns (address)
{
function verifyInvocationSignature(
SignedInvocation calldata signedInvocation
) public view returns (address) {
bytes32 sigHash = getInvocationsTypedDataHash(
signedInvocation.invocations
);
address recoveredSignatureSigner = recover(
address recoveredSignatureSigner = flexibleRecover(
sigHash,
signedInvocation.signature
signedInvocation.signature,
signedInvocation.signerIsContract
);
return recoveredSignatureSigner;
}

function flexibleRecover(
bytes32 _hash,
bytes calldata _signature,
bool isContractAccount
) internal view returns (address) {
if (isContractAccount) {
address intendedSender = address(bytes20(_signature[0:20]));
bytes calldata proof = _signature[20:_signature.length];
_callERC1271isValidSignature(intendedSender, _hash, proof);
return intendedSender;
} else {
return recover(_hash, _signature);
}
}

function _callERC1271isValidSignature(
address _addr,
bytes32 _hash,
bytes calldata _signature
) internal view {
bytes4 result = IERC1271Wallet(_addr).isValidSignature(
_hash,
_signature
);
require(result == 0x1626ba7e, "INVALID_SIGNATURE");
}

// --------------------------------------
// WRITES
// --------------------------------------
Expand Down
16 changes: 7 additions & 9 deletions contracts/DelegatableCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.15;

import {EIP712Decoder, EIP712DOMAIN_TYPEHASH} from "./TypesAndDecoders.sol";
import {Delegation, Invocation, Invocations, SignedInvocation, SignedDelegation, Transaction, ReplayProtection, CaveatEnforcer} from "./CaveatEnforcer.sol";
import {IERC1271Wallet} from "./interfaces/IERC1271Wallet.sol";

abstract contract DelegatableCore is EIP712Decoder {
/// @notice Account delegation nonce manager
Expand All @@ -16,11 +17,9 @@ abstract contract DelegatableCore is EIP712Decoder {
return multiNonce[intendedSender][queue];
}

function verifyDelegationSignature(SignedDelegation memory signedDelegation)
public
view
virtual
returns (address);
function verifyDelegationSignature(
SignedDelegation calldata signedDelegation
) public view virtual returns (address);

function _enforceReplayProtection(
address intendedSender,
Expand Down Expand Up @@ -52,7 +51,7 @@ abstract contract DelegatableCore is EIP712Decoder {
returns (bool success)
{
for (uint256 x = 0; x < batch.length; x++) {
Invocation memory invocation = batch[x];
Invocation calldata invocation = batch[x];
address intendedSender;
address canGrant;

Expand All @@ -65,9 +64,8 @@ abstract contract DelegatableCore is EIP712Decoder {
bytes32 authHash = 0x0;

for (uint256 d = 0; d < invocation.authority.length; d++) {
SignedDelegation memory signedDelegation = invocation.authority[
d
];
SignedDelegation calldata signedDelegation = invocation
.authority[d];
address delegationSigner = verifyDelegationSignature(
signedDelegation
);
Expand Down
52 changes: 41 additions & 11 deletions contracts/DelegatableFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {EIP712DOMAIN_TYPEHASH} from "./TypesAndDecoders.sol";
import {Delegation, Invocation, Invocations, SignedInvocation, SignedDelegation} from "./CaveatEnforcer.sol";
import {DelegatableCore} from "./DelegatableCore.sol";
import {IDelegatable} from "./interfaces/IDelegatable.sol";
import {IERC1271Wallet} from "./interfaces/IERC1271Wallet.sol";

/* @notice AppStorage is used so ERC2535 Diamond facets do not clobber each others' storage.
* https://eip2535diamonds.substack.com/p/keep-your-data-right-in-eip2535-diamonds?utm_source=substack&utm_campaign=post_embed&utm_medium=web
Expand Down Expand Up @@ -92,37 +93,66 @@ contract DelegatableFacet is IDelegatable, DelegatableCore {
return keccak256(encoded);
}

function verifyDelegationSignature(SignedDelegation memory signedDelegation)
function verifyDelegationSignature(
SignedDelegation calldata signedDelegation
)
public
view
virtual
override(IDelegatable, DelegatableCore)
returns (address)
{
Delegation memory delegation = signedDelegation.delegation;
Delegation calldata delegation = signedDelegation.delegation;
bytes32 sigHash = getDelegationTypedDataHash(delegation);
address recoveredSignatureSigner = recover(
address recoveredSignatureSigner = flexibleRecover(
sigHash,
signedDelegation.signature
signedDelegation.signature,
signedDelegation.signerIsContract
);
return recoveredSignatureSigner;
}

function verifyInvocationSignature(SignedInvocation memory signedInvocation)
public
view
returns (address)
{
function verifyInvocationSignature(
SignedInvocation calldata signedInvocation
) public view returns (address) {
bytes32 sigHash = getInvocationsTypedDataHash(
signedInvocation.invocations
);
address recoveredSignatureSigner = recover(
address recoveredSignatureSigner = flexibleRecover(
sigHash,
signedInvocation.signature
signedInvocation.signature,
signedInvocation.signerIsContract
);
return recoveredSignatureSigner;
}

function flexibleRecover(
bytes32 _hash,
bytes calldata _signature,
bool isContractAccount
) internal view returns (address) {
if (isContractAccount) {
address intendedSender = address(bytes20(_signature[0:20]));
bytes calldata proof = _signature[20:_signature.length];
_callERC1271isValidSignature(intendedSender, _hash, proof);
return intendedSender;
} else {
return recover(_hash, _signature);
}
}

function _callERC1271isValidSignature(
address _addr,
bytes32 _hash,
bytes calldata _signature
) internal view {
bytes4 result = IERC1271Wallet(_addr).isValidSignature(
_hash,
_signature
);
require(result == 0x1626ba7e, "INVALID_SIGNATURE");
}

// --------------------------------------
// WRITES
// --------------------------------------
Expand Down
52 changes: 41 additions & 11 deletions contracts/DelegatableRelay.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {EIP712DOMAIN_TYPEHASH} from "./TypesAndDecoders.sol";
import {Delegation, Invocation, Invocations, SignedInvocation, SignedDelegation} from "./CaveatEnforcer.sol";
import {DelegatableRelayCore} from "./DelegatableRelayCore.sol";
import {IDelegatable} from "./interfaces/IDelegatable.sol";
import {IERC1271Wallet} from "./interfaces/IERC1271Wallet.sol";

contract DelegatableRelay is IDelegatable, DelegatableRelayCore {
/// @notice The hash of the domain separator used in the EIP712 domain hash.
Expand Down Expand Up @@ -75,37 +76,66 @@ contract DelegatableRelay is IDelegatable, DelegatableRelayCore {
return keccak256(encoded);
}

function verifyDelegationSignature(SignedDelegation memory signedDelegation)
function verifyDelegationSignature(
SignedDelegation calldata signedDelegation
)
public
view
virtual
override(IDelegatable, DelegatableRelayCore)
returns (address)
{
Delegation memory delegation = signedDelegation.delegation;
Delegation calldata delegation = signedDelegation.delegation;
bytes32 sigHash = getDelegationTypedDataHash(delegation);
address recoveredSignatureSigner = recover(
address recoveredSignatureSigner = flexibleRecover(
sigHash,
signedDelegation.signature
signedDelegation.signature,
signedDelegation.signerIsContract
);
return recoveredSignatureSigner;
}

function verifyInvocationSignature(SignedInvocation memory signedInvocation)
public
view
returns (address)
{
function verifyInvocationSignature(
SignedInvocation calldata signedInvocation
) public view returns (address) {
bytes32 sigHash = getInvocationsTypedDataHash(
signedInvocation.invocations
);
address recoveredSignatureSigner = recover(
address recoveredSignatureSigner = flexibleRecover(
sigHash,
signedInvocation.signature
signedInvocation.signature,
signedInvocation.signerIsContract
);
return recoveredSignatureSigner;
}

function flexibleRecover(
bytes32 _hash,
bytes calldata _signature,
bool isContractAccount
) internal view returns (address) {
if (isContractAccount) {
address intendedSender = address(bytes20(_signature[0:20]));
bytes calldata proof = _signature[20:_signature.length];
_callERC1271isValidSignature(intendedSender, _hash, proof);
return intendedSender;
} else {
return recover(_hash, _signature);
}
}

function _callERC1271isValidSignature(
address _addr,
bytes32 _hash,
bytes calldata _signature
) internal view {
bytes4 result = IERC1271Wallet(_addr).isValidSignature(
_hash,
_signature
);
require(result == 0x1626ba7e, "INVALID_SIGNATURE");
}

// --------------------------------------
// WRITES
// --------------------------------------
Expand Down
19 changes: 8 additions & 11 deletions contracts/DelegatableRelayCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@ abstract contract DelegatableRelayCore is EIP712Decoder {
return multiNonce[intendedSender][queue];
}

function verifyDelegationSignature(SignedDelegation memory signedDelegation)
public
view
virtual
returns (address);
function verifyDelegationSignature(
SignedDelegation calldata signedDelegation
) public view virtual returns (address);

function _enforceReplayProtection(
address intendedSender,
Expand Down Expand Up @@ -52,7 +50,7 @@ abstract contract DelegatableRelayCore is EIP712Decoder {
returns (bool success)
{
for (uint256 x = 0; x < batch.length; x++) {
Invocation memory invocation = batch[x];
Invocation calldata invocation = batch[x];
address intendedSender;
address canGrant;

Expand All @@ -65,9 +63,8 @@ abstract contract DelegatableRelayCore is EIP712Decoder {
bytes32 authHash = 0x0;

for (uint256 d = 0; d < invocation.authority.length; d++) {
SignedDelegation memory signedDelegation = invocation.authority[
d
];
SignedDelegation calldata signedDelegation = invocation
.authority[d];
address delegationSigner = verifyDelegationSignature(
signedDelegation
);
Expand All @@ -83,7 +80,7 @@ abstract contract DelegatableRelayCore is EIP712Decoder {
"DelegatableCore:invalid-delegation-signer"
);

Delegation memory delegation = signedDelegation.delegation;
Delegation calldata delegation = signedDelegation.delegation;
require(
delegation.authority == authHash,
"DelegatableCore:invalid-authority-delegation-link"
Expand Down Expand Up @@ -118,7 +115,7 @@ abstract contract DelegatableRelayCore is EIP712Decoder {
}

// Here we perform the requested invocation.
Transaction memory transaction = invocation.transaction;
Transaction calldata transaction = invocation.transaction;

// TODO(@kames): Can we bubble up the error message from the enforcer? Why not? Optimizations?
success = _execute(
Expand Down
Loading