-
Notifications
You must be signed in to change notification settings - Fork 1k
Allow Safe to Own Itself #998
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This PR reverts an old change (See #229 and #259) and allows the Safe to once again own itself. This is a step towards 7702 support, whereby we want the EOA that delegates to a Safe to be able to sign transactions for itself. The restriction was originally put in place because `execTransaction` would call `isValidSignature` (which used to be implemented on the Safe itself and not as part of the compatibility fallback handler) on itself, where the `msg.sender` would be the Safe itself, and allow for trivial "approved hash" signatures (through [this](https://github.com/safe-global/safe-smart-account/blob/36db12a140331c522e773849ebc87d39f5abae1e/contracts/GnosisSafe.sol#L244-L245) mechanism). This is no longer possible since v1.3.0, as the `isValidSignature` call would be handled by the fallback handler, meaning that the `msg.sender` that can trivially sign "approve hash" signatures is no longer the Safe itself but the configured fallback handler. Since #866 and starting in v1.5.0 the `CompatibilityFallbackHandler` is implemented to disallow "approve hash" signatures regardless of the caller, further eliminating the requirement for the restriction. ### Increasing Threshold Concerns One concern with this change, and removing the restriction on having the Safe own itself, is that the Safe cannot sign for itself, so you can potentially block access to the account completely, by requiring the Safe "self-owner" to be included as part of the signing threshold. For example, if you have a n/n Safe (so `threshold == ownerCount` and one of the owners is the Safe itself, then the Safe will not be able to ever produce a valid signature).
@@ -165,7 +154,7 @@ describe("Safe", () => { | |||
} = await setupTests(); | |||
await expect( | |||
template.setup([user2.address, user2.address], 2, AddressZero, "0x", AddressZero, AddressZero, 0, AddressZero), | |||
).to.be.revertedWith("GS203"); | |||
).to.be.revertedWith("GS204"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error duplicate owner is now consistently "GS204".
} as const; | ||
const signatures = buildSignatureBytes([selfSignature]); | ||
|
||
await expect(safe["checkSignatures(address,bytes32,bytes)"](user1.address, txHash, signatures)).to.be.revertedWith("GS025"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that if we change the CompatibilityFallbackHandler
to not use address(0)
as the executor, then this test would fail:
diff --git a/contracts/handler/CompatibilityFallbackHandler.sol b/contracts/handler/CompatibilityFallbackHandler.sol
index 275797d..e652ad0 100644
--- a/contracts/handler/CompatibilityFallbackHandler.sol
+++ b/contracts/handler/CompatibilityFallbackHandler.sol
@@ -80,7 +80,7 @@ contract CompatibilityFallbackHandler is TokenCallbackHandler, ISignatureValidat
} else {
// We explicitly do not allow caller approved signatures for EIP-1271 to prevent unexpected behaviour. This
// is done by setting the executor address to `0` which can never be an owner of the Safe.
- safe.checkSignatures(address(0), messageHash, _signature);
+ safe.checkSignatures(msg.sender, messageHash, _signature);
}
return EIP1271_MAGIC_VALUE;
}
1) Safe
checkSignatures
should not allow trivial signatures when the Safe owns itself:
AssertionError: Expected transaction to be reverted with reason 'GS025', but it didn't revert
at async Context.<anonymous> (test/core/Safe.Signatures.spec.ts:511:13)
Tagging with |
It is no longer true, and is allowed.
This change was originally proposed by @akshay-ap
This PR reverts an old change (See #229 and #259) and allows the Safe to once again own itself. This is a step towards 7702 support (#997), whereby we want the EOA that delegates to a Safe to be able to sign transactions for itself.
The restriction was originally put in place because
execTransaction
would callisValidSignature
on itself (which used to be implemented on the Safe itself and not as part of the compatibility fallback handler), where themsg.sender
would be the Safe itself, and allow for trivial "approved hash" signatures (throughthis mechanism).
This is no longer possible since v1.3.0, as the
isValidSignature
call would be handled by the fallback handler, meaning that themsg.sender
that can trivially sign "approve hash" signatures is no longer the Safe itself but the configured fallback handler. Since #866 and starting in v1.5.0 theCompatibilityFallbackHandler
is implemented to disallow "approve hash" signatures regardless of the caller, further eliminating the requirement for the restriction.Increasing Threshold Concerns
One concern with this change, and removing the restriction on having the Safe own itself, is that the Safe cannot sign for itself, so you can potentially block access to the account completely, by requiring the Safe "self-owner" to be included as part of the signing threshold. For example, if you have a n/n Safe (so
threshold == ownerCount
) and one of the owners is the Safe itself, then the Safe will not be able to ever produce a valid signature.