-
Notifications
You must be signed in to change notification settings - Fork 929
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create a separate contract for EIP7702
- Loading branch information
Showing
4 changed files
with
148 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
pragma solidity >=0.7.0 <0.9.0; | ||
|
||
import {ISafe} from "../interfaces/ISafe.sol"; | ||
import {Safe} from "../Safe.sol"; | ||
|
||
/** | ||
* @title SafeEIP7702 - A multisignature wallet with support for confirmations using signed messages based on EIP-712. | ||
* This contract is designed to be used as a delegation designator for EIP-7702. | ||
* @dev Most important concepts: | ||
* - Threshold: Number of required confirmations for a Safe transaction. | ||
* - Owners: List of addresses that control the Safe. They are the only ones that can add/remove owners, change the threshold and | ||
* approve transactions. Managed in `OwnerManager`. | ||
* - Transaction Hash: Hash of a transaction is calculated using the EIP-712 typed structured data hashing scheme. | ||
* - Nonce: Each transaction should have a different nonce to prevent replay attacks. | ||
* - Signature: A valid signature of an owner of the Safe for a transaction hash. | ||
* - Guards: Guards are contracts that can execute pre- and post- transaction checks. There are two types of guards: | ||
* 1. Transaction Guard: managed in `GuardManager` for transactions executed with `execTransaction`. | ||
* 2. Module Guard: managed in `ModuleManager` for transactions executed with `execTransactionFromModule` | ||
* - Modules: Modules are contracts that can be used to extend the write functionality of a Safe. Managed in `ModuleManager`. | ||
* - Fallback: Fallback handler is a contract that can provide additional read-only functional for Safe. Managed in `FallbackManager`. | ||
* Note: This version of the implementation contract doesn't emit events for the sake of gas efficiency and therefore requires a tracing node for indexing/ | ||
* For the events-based implementation see `SafeL2.sol`. | ||
* @author Stefan George - @Georgi87 | ||
* @author Richard Meissner - @rmeissner | ||
*/ | ||
contract SafeEIP7702 is Safe { | ||
/** | ||
* @inheritdoc ISafe | ||
*/ | ||
function setup( | ||
address[] calldata /*_owners*/, | ||
uint256 /*_threshold*/, | ||
address /*to*/, | ||
bytes calldata /*data*/, | ||
address /*fallbackHandler*/, | ||
address /*paymentToken*/, | ||
uint256 /*payment*/, | ||
address payable /*paymentReceiver*/ | ||
) external pure override { | ||
revertWithError("GS003"); | ||
} | ||
|
||
function setupEIP7702( | ||
address to, | ||
bytes calldata data, | ||
address fallbackHandler, | ||
address paymentToken, | ||
uint256 payment, | ||
address payable paymentReceiver, | ||
bytes calldata signature | ||
) external { | ||
address[] memory _owners = new address[](1); | ||
_owners[0] = address(this); | ||
|
||
// setupOwners checks if the Threshold is already set, therefore preventing that this method is called twice | ||
setupOwners(_owners, 1); | ||
if (fallbackHandler != address(0)) internalSetFallbackHandler(fallbackHandler); | ||
// As setupOwners can only be called if the contract has not been initialized we don't need a check for setupModules | ||
setupModules(to, data); | ||
|
||
if (payment > 0) { | ||
// To avoid running into issues with EIP-170 we reuse the handlePayment function (to avoid adjusting code of that has been verified we do not adjust the method itself) | ||
// baseGas = 0, gasPrice = 1 and gas = payment => amount = (payment + 0) * 1 = payment | ||
handlePayment(payment, 0, 1, paymentToken, paymentReceiver); | ||
} | ||
checkSignatures(keccak256(abi.encode(to, data, fallbackHandler, paymentToken, payment, paymentReceiver)), signature); | ||
emit SafeSetup(msg.sender, _owners, 1, to, fallbackHandler); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
pragma solidity >=0.7.0 <0.9.0; | ||
|
||
// The import is used in the @inheritdoc, false positive | ||
// solhint-disable-next-line no-unused-import | ||
import {ModuleManager} from "../base/ModuleManager.sol"; | ||
import {Safe, Enum} from "../Safe.sol"; | ||
import {SafeEIP7702} from "./SafeEIP7702.sol"; | ||
|
||
/** | ||
* @title SafeL2 - An implementation of the Safe contract that emits additional events on transaction executions. | ||
* @notice For a more complete description of the Safe contract, please refer to the main Safe contract `Safe.sol`. | ||
* @author Stefan George - @Georgi87 | ||
* @author Richard Meissner - @rmeissner | ||
*/ | ||
contract SafeEIP7702L2 is SafeEIP7702 { | ||
event SafeMultiSigTransaction( | ||
address to, | ||
uint256 value, | ||
bytes data, | ||
Enum.Operation operation, | ||
uint256 safeTxGas, | ||
uint256 baseGas, | ||
uint256 gasPrice, | ||
address gasToken, | ||
address payable refundReceiver, | ||
bytes signatures, | ||
// We combine nonce, sender and threshold into one to avoid stack too deep | ||
// Dev note: additionalInfo should not contain `bytes`, as this complicates decoding | ||
bytes additionalInfo | ||
); | ||
|
||
event SafeModuleTransaction(address module, address to, uint256 value, bytes data, Enum.Operation operation); | ||
|
||
/** | ||
* @inheritdoc Safe | ||
*/ | ||
function onBeforeExecTransaction( | ||
address to, | ||
uint256 value, | ||
bytes calldata data, | ||
Enum.Operation operation, | ||
uint256 safeTxGas, | ||
uint256 baseGas, | ||
uint256 gasPrice, | ||
address gasToken, | ||
address payable refundReceiver, | ||
bytes memory signatures | ||
) internal override { | ||
bytes memory additionalInfo; | ||
{ | ||
additionalInfo = abi.encode(nonce, msg.sender, threshold); | ||
} | ||
emit SafeMultiSigTransaction( | ||
to, | ||
value, | ||
data, | ||
operation, | ||
safeTxGas, | ||
baseGas, | ||
gasPrice, | ||
gasToken, | ||
refundReceiver, | ||
signatures, | ||
additionalInfo | ||
); | ||
} | ||
|
||
/** | ||
* @inheritdoc ModuleManager | ||
*/ | ||
function onBeforeExecTransactionFromModule(address to, uint256 value, bytes memory data, Enum.Operation operation) internal override { | ||
emit SafeModuleTransaction(msg.sender, to, value, data, operation); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters