diff --git a/contracts/core/BaseUtils.sol b/contracts/core/BaseUtils.sol index 3cc8c78..672ccf3 100644 --- a/contracts/core/BaseUtils.sol +++ b/contracts/core/BaseUtils.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import { ERC20, OwnerSettings } from "contracts/core/OwnerSettings.sol"; -import { ECDSA } from "contracts/lib/utils/ECDSA.sol"; +import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import { MerkleProof as Merkle } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; @@ -44,7 +44,7 @@ abstract contract BaseUtils is if ( !validBacenSigners( _castAddrToKey( - ECDSA.recoverCalldata( + ECDSA.recover( MessageHashUtils.toEthSignedMessageHash( _message ), diff --git a/contracts/core/OwnerSettings.sol b/contracts/core/OwnerSettings.sol index a4cac75..be40baa 100644 --- a/contracts/core/OwnerSettings.sol +++ b/contracts/core/OwnerSettings.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import { ERC2771Context as ERC2771 } from "contracts/lib/metatx/ERC2771Context.sol"; +import { ERC2771Context as ERC2771 } from "@openzeppelin/contracts/metatx/ERC2771Context.sol"; import { ERC20, SafeTransferLib } from "contracts/lib/utils/SafeTransferLib.sol"; import { IReputation } from "contracts/lib/interfaces/IReputation.sol"; import { EventAndErrors } from "contracts/core/EventAndErrors.sol"; @@ -42,48 +42,6 @@ abstract contract OwnerSettings is /// ███ Owner Only █████████████████████████████████████████████████████████ - function setTrustedFowarders( - address[] memory forwarders, - bool[] memory states - ) external onlyOwner { - assembly ("memory-safe") { - // first 32 bytes eq to array's length - let fLen := mload(forwarders) - // halts execution if forwarders.length eq 0 - if iszero(fLen) { - invalid() - } - // revert with `LengthMismatch()` - if iszero(eq(fLen, mload(states))) { - mstore(0x00, 0xff633a38) - revert(0x1c, 0x04) - } - let fLoc := add(forwarders, 0x20) - let sLoc := add(states, 0x20) - for { - let end := add(fLoc, shl(5, fLen)) - } iszero(eq(fLoc, end)) { - fLoc := add(fLoc, 0x20) - sLoc := add(sLoc, 0x20) - } { - // cache hashmap entry in scratch space - mstore(0x20, trustedForwarders.slot) - mstore(0x00, mload(fLoc)) - // let mapSlot := keccak256(0x00, 0x40) - sstore(keccak256(0x00, 0x40), mload(sLoc)) - - // emit TrustedForwarderUpdated(address, bool) - log3( - 0, - 0, - _TRUSTED_FORWARDER_UPDATED_EVENT_SIGNATURE, - mload(fLoc), - mload(sLoc) - ) - } - } - } - /// @dev Contract's underlying balance withdraw method. /// @dev Function sighash: 0x5fd8c710. function withdrawBalance() external onlyOwner { diff --git a/contracts/lib/metatx/ERC2771Context.sol b/contracts/lib/metatx/ERC2771Context.sol deleted file mode 100644 index 82d8734..0000000 --- a/contracts/lib/metatx/ERC2771Context.sol +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity >=0.8.4; - -/// @author OpenZeppelin Contracts v4.4.1 (utils/Context.sol) -/// (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Context.sol) - -/// @dev Provides information about the current execution context, including the -/// sender of the transaction and its data. While these are generally available -/// via msg.sender and msg.data, they should not be accessed in such a direct -/// manner, since when dealing with meta-transactions the account sending and -/// paying for execution may not be the actual sender (as far as an application -/// is concerned). -/// -/// This contract is only required for intermediate, library-like contracts. -abstract contract Context { - function _msgSender() - internal - view - virtual - returns (address) - { - return msg.sender; - } - - function _msgData() - internal - view - virtual - returns (bytes calldata) - { - return msg.data; - } -} - -/// @author Modified from OpenZeppelin Contracts (last updated v4.7.0) (metatx/ERC2771Context.sol) -/// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/metatx/ERC2771Context.sol - -/// @dev Context variant with ERC2771 support. -abstract contract ERC2771Context is Context { - // address private immutable _trustedForwarder; - mapping(address => bool) public trustedForwarders; - - /// @custom:oz-upgrades-unsafe-allow constructor - // constructor(address trustedForwarder) { - // _trustedForwarder = trustedForwarder; - // } - - function _msgSender() - internal - view - virtual - override - returns (address sender) - { - if (trustedForwarders[msg.sender]) { - // The assembly code is more direct than the Solidity version using `abi.decode`. - /// @solidity memory-safe-assembly - assembly { - sender := shr( - 96, - calldataload(sub(calldatasize(), 20)) - ) - } - } else { - return super._msgSender(); - } - } - - function isTrustedForwarder(address forwarder) public view virtual returns (bool) { - return trustedForwarders[forwarder]; - } - - function _msgData() - internal - view - virtual - override - returns (bytes calldata) - { - if (isTrustedForwarder(msg.sender)) { - return msg.data[:msg.data.length - 20]; - } else { - return super._msgData(); - } - } -} diff --git a/contracts/lib/utils/ECDSA.sol b/contracts/lib/utils/ECDSA.sol deleted file mode 100644 index 9cf53fb..0000000 --- a/contracts/lib/utils/ECDSA.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.8.4; - -/// @notice Gas optimized ECDSA wrapper. -/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol) -/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol) -/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol) -library ECDSA { - /// @dev The signature is invalid. - error InvalidSignature(); - - /// @dev The number which `s` must not exceed in order for - /// the signature to be non-malleable. - bytes32 private constant _MALLEABILITY_THRESHOLD = - 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0; - - /// @dev Recovers the signer's address from a message digest `hash`, - /// and the `signature`. - /// - /// This function does NOT accept EIP-2098 short form signatures. - /// Use `recover(bytes32 hash, bytes32 r, bytes32 vs)` for EIP-2098 - /// short form signatures instead. - function recoverCalldata( - bytes32 hash, - bytes calldata signature - ) internal view returns (address result) { - /// @solidity memory-safe-assembly - assembly { - // Copy the free memory pointer so that we can restore it later. - let m := mload(0x40) - // Directly copy `r` and `s` from the calldata. - calldatacopy(0x40, signature.offset, 0x40) - // Store the `hash` in the scratch space. - mstore(0x00, hash) - // Compute `v` and store it in the scratch space. - mstore( - 0x20, - byte( - 0, - calldataload(add(signature.offset, 0x40)) - ) - ) - pop( - staticcall( - gas(), // Amount of gas left for the transaction. - and( - // If the signature is exactly 65 bytes in length. - eq(signature.length, 65), - // If `s` in lower half order, such that the signature is not malleable. - lt( - mload(0x60), - add(_MALLEABILITY_THRESHOLD, 1) - ) - ), // Address of `ecrecover`. - 0x00, // Start of input. - 0x80, // Size of input. - 0x00, // Start of output. - 0x20 // Size of output. - ) - ) - result := mload(0x00) - // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. - if iszero(returndatasize()) { - // Store the function selector of `InvalidSignature()`. - mstore(0x00, 0x8baa579f) - // Revert with (offset, size). - revert(0x1c, 0x04) - } - // Restore the zero slot. - mstore(0x60, 0) - // Restore the free memory pointer. - mstore(0x40, m) - } - } - - /// @dev Returns an Ethereum Signed Message, created from a `hash`. - /// This produces a hash corresponding to the one signed with the - /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) - /// JSON-RPC method as part of EIP-191. - function toEthSignedMessageHash( - bytes32 hash - ) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - // Store into scratch space for keccak256. - mstore(0x20, hash) - mstore( - 0x00, - "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32" - ) - // 0x40 - 0x04 = 0x3c - result := keccak256(0x04, 0x3c) - } - } -} diff --git a/contracts/p2pix.sol b/contracts/p2pix.sol index 641da79..9608027 100644 --- a/contracts/p2pix.sol +++ b/contracts/p2pix.sol @@ -9,6 +9,7 @@ pragma solidity ^0.8.19; /// import { OwnerSettings, ERC20, SafeTransferLib } from "contracts/core/OwnerSettings.sol"; +import { ERC2771Context as ERC2771 } from "@openzeppelin/contracts/metatx/ERC2771Context.sol"; import { BaseUtils } from "contracts/core/BaseUtils.sol"; import { DataTypes as DT } from "contracts/core/DataTypes.sol"; @@ -33,8 +34,10 @@ contract P2PIX is BaseUtils { address[] memory validSigners, address _reputation, ERC20[] memory tokens, - bool[] memory tokenStates + bool[] memory tokenStates, + address trustedForwarder ) + ERC2771(trustedForwarder) OwnerSettings( defaultBlocks, validSigners, diff --git a/package.json b/package.json index 23cca9c..7ef8e47 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "@nomicfoundation/hardhat-verify": "^2.1.0", "@nomicfoundation/hardhat-viem": "^2.1.0", "@nomicfoundation/ignition-core": "^0.15.13", - "@openzeppelin/contracts": "^5.4.0", + "@openzeppelin/contracts": "^5.5.0-rc.0", "@typechain/ethers-v6": "^0.5.1", "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.3.20", diff --git a/scripts/2-deploy-p2pix.ts b/scripts/2-deploy-p2pix.ts index a6d1f1a..57bea46 100644 --- a/scripts/2-deploy-p2pix.ts +++ b/scripts/2-deploy-p2pix.ts @@ -29,6 +29,7 @@ const main = async () => { reputation.target, [deploysJson.token], [true], + ethers.ZeroAddress, ]); reputation = await reputation.waitForDeployment(); diff --git a/test/utils/fixtures.ts b/test/utils/fixtures.ts index 8fb483a..1cda9c3 100644 --- a/test/utils/fixtures.ts +++ b/test/utils/fixtures.ts @@ -93,6 +93,7 @@ export async function p2pixFixture(): Promise { reputation.target, [erc20.target], [true], + ethers.ZeroAddress, ]); const multicall = await ethers.deployContract("Multicall"); diff --git a/yarn.lock b/yarn.lock index 37d5f23..b5af73e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -988,10 +988,10 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts@npm:^5.4.0": - version: 5.4.0 - resolution: "@openzeppelin/contracts@npm:5.4.0" - checksum: 10/4f7f926ebd98279ba8223cae5d2cd38e0806e60e3e3a615c9d739ffab870ffab7a1e85f47092faa123c0f26d1699ca15252adea8bcdcaf360b21781acc93b218 +"@openzeppelin/contracts@npm:^5.5.0-rc.0": + version: 5.5.0-rc.0 + resolution: "@openzeppelin/contracts@npm:5.5.0-rc.0" + checksum: 10/caa60a0963a4a0d1ee267ec99e4fda7b952fa8743a59dcbf3ea4a0b11b9cd6c93524b92939fd6482c52b8374ec68d6e6399626ea23e7c96730ada2d8452c4396 languageName: node linkType: hard @@ -4570,7 +4570,7 @@ __metadata: "@nomicfoundation/hardhat-verify": "npm:^2.1.0" "@nomicfoundation/hardhat-viem": "npm:^2.1.0" "@nomicfoundation/ignition-core": "npm:^0.15.13" - "@openzeppelin/contracts": "npm:^5.4.0" + "@openzeppelin/contracts": "npm:^5.5.0-rc.0" "@typechain/ethers-v6": "npm:^0.5.1" "@typechain/hardhat": "npm:^9.1.0" "@types/chai": "npm:^4.3.20"