-
Notifications
You must be signed in to change notification settings - Fork 11.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce SequentialOperations and ParallelOperations between EIP712 …
…and signature-based operations like ERC20Permit, Votes, Governor, MinimalForwarder
- Loading branch information
Showing
12 changed files
with
188 additions
and
69 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
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
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,64 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "../Context.sol"; | ||
import "../Nonces.sol"; | ||
import "./EIP712.sol"; | ||
import "./ECDSA.sol"; | ||
|
||
/** | ||
* @dev Provides tracking nonces per address and operation. Operation ids should be unique. | ||
*/ | ||
abstract contract ParallelOperations is Context, EIP712 { | ||
mapping(bytes32 => mapping(address => mapping(uint256 => bool))) private _usedOperationIds; | ||
|
||
function isOperationIdAvailable(bytes32 operationTypehash, address owner, uint256 operationId) public view virtual returns (bool) { | ||
return !_usedOperationIds[operationTypehash][owner][operationId]; | ||
} | ||
|
||
function useOperationId(bytes32 operationTypehash, uint256 operationId) public virtual { | ||
_useOperationId(operationTypehash, _msgSender(), operationId); | ||
} | ||
|
||
function _validateParallelOperation( | ||
bytes32 operationTypehash, | ||
bytes32 operationHash, | ||
uint256 operationId, | ||
bytes memory signature | ||
) internal virtual returns(address signer) { | ||
signer = ECDSA.recover(_hashTypedDataV4(operationHash), signature); | ||
_useOperationId(operationTypehash, signer, operationId); | ||
} | ||
|
||
function _validateParallelOperation( | ||
bytes32 operationTypehash, | ||
bytes32 operationHash, | ||
uint256 operationId, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
) internal virtual returns(address signer) { | ||
signer = ECDSA.recover(_hashTypedDataV4(operationHash), v, r, s); | ||
_useOperationId(operationTypehash, signer, operationId); | ||
} | ||
|
||
function _validateParallelOperation( | ||
bytes32 operationTypehash, | ||
bytes32 operationHash, | ||
uint256 operationId, | ||
bytes32 r, | ||
bytes32 vs | ||
) internal virtual returns(address signer) { | ||
signer = ECDSA.recover(_hashTypedDataV4(operationHash), r, vs); | ||
_useOperationId(operationTypehash, signer, operationId); | ||
} | ||
|
||
/// @dev Method made non-virtual to deny changing logic of parallel operations invalidation. | ||
function _useOperationId(bytes32 operationTypehash, address owner, uint256 operationId) internal { | ||
require( | ||
!_usedOperationIds[operationTypehash][owner][operationId], | ||
"ParallelOperations: invalid operation id" | ||
); | ||
_usedOperationIds[operationTypehash][owner][operationId] = true; | ||
} | ||
} |
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,62 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
import "../Context.sol"; | ||
import "../Nonces.sol"; | ||
import "./EIP712.sol"; | ||
import "./ECDSA.sol"; | ||
|
||
/** | ||
* @dev Provides tracking nonces per address and operation. Nonces will only increment. | ||
*/ | ||
abstract contract SequentialOperations is Context, EIP712 { | ||
using Nonces for Nonces.Data; | ||
|
||
mapping(bytes32 => Nonces.Data) private _nonces; | ||
|
||
function operationNonces(bytes32 operationTypehash, address owner) public view virtual returns (uint256) { | ||
return _nonces[operationTypehash].nonces(owner); | ||
} | ||
|
||
function useOperationNonce(bytes32 operationTypehash, uint256 nonce) public virtual { | ||
_useOperationNonce(operationTypehash, _msgSender(), nonce); | ||
} | ||
|
||
function _validateSequentialOperation( | ||
bytes32 operationTypehash, | ||
bytes32 operationHash, | ||
uint256 nonce, | ||
bytes memory signature | ||
) internal virtual returns(address signer) { | ||
signer = ECDSA.recover(_hashTypedDataV4(operationHash), signature); | ||
_useOperationNonce(operationTypehash, signer, nonce); | ||
} | ||
|
||
function _validateSequentialOperation( | ||
bytes32 operationTypehash, | ||
bytes32 operationHash, | ||
uint256 nonce, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
) internal virtual returns(address signer) { | ||
signer = ECDSA.recover(_hashTypedDataV4(operationHash), v, r, s); | ||
_useOperationNonce(operationTypehash, signer, nonce); | ||
} | ||
|
||
function _validateSequentialOperation( | ||
bytes32 operationTypehash, | ||
bytes32 operationHash, | ||
uint256 nonce, | ||
bytes32 r, | ||
bytes32 vs | ||
) internal virtual returns(address signer) { | ||
signer = ECDSA.recover(_hashTypedDataV4(operationHash), r, vs); | ||
_useOperationNonce(operationTypehash, signer, nonce); | ||
} | ||
|
||
/// @dev Method made non-virtual to deny changing logic of sequential operations invalidation. | ||
function _useOperationNonce(bytes32 operationTypehash, address owner, uint256 nonce) internal { | ||
require(nonce == _nonces[operationTypehash].useNonce(owner), "SequentialOperations: invalid nonce"); | ||
} | ||
} |
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
Oops, something went wrong.