diff --git a/contracts/AccessTokenConsumer.sol b/contracts/AccessTokenConsumer.sol index 3fb3645..37df68c 100644 --- a/contracts/AccessTokenConsumer.sol +++ b/contracts/AccessTokenConsumer.sol @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.13; -import { IAccessTokenVerifier, AccessToken, FunctionCall } from "./interfaces/IAccessTokenVerifier.sol"; +import { IAccessTokenVerifier } from "./interfaces/IAccessTokenVerifier.sol"; +import { LibAccessTokenConsumer } from "./LibAccessTokenConsumer.sol"; /** * @title AccessTokenConsumer @@ -18,6 +19,9 @@ contract AccessTokenConsumer { // Stores whether an EAT has already been used mapping(bytes32 => bool) private _accessTokenUsed; + error AccessTokenUsed(); + error VerificationFailed(); + constructor(address accessTokenVerifier) { verifier = IAccessTokenVerifier(accessTokenVerifier); } @@ -27,15 +31,8 @@ contract AccessTokenConsumer { * by requiring a valid EAT to be provided. * If valid, it marks the EAT as consumed. */ - modifier requiresAuth( - uint8 v, - bytes32 r, - bytes32 s, - uint256 expiry - ) { - // VF -> Verification Failure - require(verify(v, r, s, expiry), "AccessToken: VF"); - _consumeAccessToken(v, r, s, expiry); + modifier requiresAuth() { + LibAccessTokenConsumer.consumeAccessToken(_accessTokenUsed, address(verifier)); _; } @@ -45,83 +42,4 @@ contract AccessTokenConsumer { function setVerifier(address newVerifier) internal { verifier = IAccessTokenVerifier(newVerifier); } - - /** - * @dev Verifies an EAT by calling the AccessTokenVerifier. - * Reverts if the EAT has already been used. - */ - function verify(uint8 v, bytes32 r, bytes32 s, uint256 expiry) internal view returns (bool) { - // AU -> Already Used - require(!_isAccessTokenUsed(v, r, s, expiry), "AccessToken: AU"); - - AccessToken memory token = constructToken(expiry); - return verifier.verify(token, v, r, s); - } - - /** - * @dev Reconstructs an EAT based on `expiry` and current function call - * to populate function signature, target contract address, caller and function parameters. - */ - function constructToken(uint256 expiry) internal view returns (AccessToken memory token) { - FunctionCall memory functionCall; - functionCall.functionSignature = msg.sig; - functionCall.target = address(this); - functionCall.caller = msg.sender; - - functionCall.parameters = extractInputs(); - token.functionCall = functionCall; - token.expiry = expiry; - } - - /** - * @dev Takes calldata and extracts non-signature, non-expiry function inputs as a byte array - * Removes all references to the proof object except any offsets related to - * other inputs that are pushed by the proof - */ - function extractInputs() public pure returns (bytes memory inputs) { - // solhint-disable-next-line no-inline-assembly - assembly { - // Allocate memory from free memory pointer - let ptr := mload(0x40) - // Copy calldata to memory - calldatacopy(ptr, 0, calldatasize()) - // Update free memory pointer to point to the end of the copied calldata - mstore(0x40, add(ptr, calldatasize())) - - // Set starting position after the first 4 bytes (function signature) - let startPos := 0x04 - // Add 128 bytes to the starting position to calculate the end position of the EAT params - // since each EAT param (v,r,s,expiry) takes 32 bytes - let endOfSigExp := add(startPos, 0x80) - // Compute the size of the remaining function parameters (end of calldata - end position of EAT params) - let totalInputSize := sub(calldatasize(), endOfSigExp) - - // Overwrite inputs pointer to free memory pointer - inputs := ptr - - // Store expected length of total byte array as first value - mstore(inputs, totalInputSize) - - // Copy bytes from end of signature and expiry section to end of calldata, - // right after the 32 bytes (0x20) reserved for totalInputSize - calldatacopy(add(inputs, 0x20), endOfSigExp, totalInputSize) - } - } - - /** - * @dev Returns whether an EAT has already been used. - */ - function _isAccessTokenUsed(uint8 v, bytes32 r, bytes32 s, uint256 expiry) internal view returns (bool) { - bytes32 accessTokenHash = keccak256(abi.encodePacked(v, r, s, expiry)); - return _accessTokenUsed[accessTokenHash]; - } - - /** - * @dev Marks an EAT as consumed/used. - */ - function _consumeAccessToken(uint8 v, bytes32 r, bytes32 s, uint256 expiry) private { - bytes32 accessTokenHash = keccak256(abi.encodePacked(v, r, s, expiry)); - - _accessTokenUsed[accessTokenHash] = true; - } } diff --git a/contracts/LibAccessTokenConsumer.sol b/contracts/LibAccessTokenConsumer.sol new file mode 100644 index 0000000..1a392a2 --- /dev/null +++ b/contracts/LibAccessTokenConsumer.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.13; + +import { IAccessTokenVerifier, AccessToken, FunctionCall } from "./interfaces/IAccessTokenVerifier.sol"; + +// Calldata constants for AccessTokenVerifier.verify +// function verify ( +// AccessToken calldata token, +// uint8 v, +// bytes32 r, +// bytes32 s +// ) +uint256 constant Verify_functionSelector = 0xfda7127900000000000000000000000000000000000000000000000000000000; +uint256 constant Verify_token_head_offset = 0x04; +uint256 constant Verify_token_head_value = 0x80; +uint256 constant Verify_v_offset = 0x24; +uint256 constant Verify_r_offset = 0x44; +uint256 constant Verify_s_offset = 0x64; + +// struct AccessToken { +// uint256 expiry; +// FunctionCall functionCall; +// } +uint256 constant Verify_expiry_offset = 0x84; +uint256 constant Verify_functionCall_head_offset = 0xa4; +uint256 constant Verify_functionCall_head_value = 0x40; + +// struct FunctionCall { +// bytes4 functionSignature; +// address target; +// address caller; +// bytes parameters; +// } +uint256 constant Verify_functionSignature_offset = 0xc4; +uint256 constant Verify_target_offset = 0xe4; +uint256 constant Verify_caller_offset = 0x0104; +uint256 constant Verify_parameters_head_offset = 0x0124; +uint256 constant Verify_parameters_head_value = 0x80; +uint256 constant Verify_parameters_length_offset = 0x0144; +uint256 constant Verify_parameters_data_offset = 0x0164; + +// Size of function selector and access token parameters - subtracted +// from calldatasize to get the length of the input parameters. +uint256 constant AccessTokenAndSelectorPrefixSize = 0x84; + +// error AccessTokenUsed() +uint256 constant AccessTokenUsed_selector = 0xb8b24f64; + +// error VerificationFailed(); +uint256 constant VerificationFailed_selector = 0x439cc0cd; + +library LibAccessTokenConsumer { + /** + * @dev Constructs an AccessToken from the current call context and verifies it + * with the provided verifier, then marks the access token as used. + * + * Reverts with `AccessTokenUsed` if the access token is not unique. + * Reverts with `VerificationFailed` if the verifier does not validate the token. + * + * note: This function assumes that the current call context had calldata beginning + * with `uint8 v, bytes32 r, bytes32 s, uint256 expiry`. + */ + function consumeAccessToken(mapping(bytes32 => bool) storage _accessTokenUsed, address verifierAddress) internal { + uint256 ptr; + assembly { + // Cache the free memory pointer to be used for calculating the access token slot + // and the call to `AccessTokenVerifier.verify`. + ptr := mload(0x40) + + // Copy (v, r, s, expiry) from calldata to memory at offset for verify calldata + calldatacopy(add(ptr, Verify_v_offset), 0x04, 0x80) + } + // Solc (or maybe hardhat) loses its mind when you combine these blocks ¯\_(ツ)_/¯ + assembly { + // Calculate the hash of the access token, equivalent to + // `keccak256(abi.encodePacked(v, r, s, expiry))` + let accessTokenHash := keccak256(add(add(ptr, Verify_v_offset), 31), 0x61) + + // Write the access token hash and the slot for `_accessTokenUsed` to memory + // to calculate the slot for `_accessTokenUsed[accessTokenHash]`. + // Mapping values are stored at keccak256(abi.encodePacked(key, slot)) + mstore(0, accessTokenHash) + mstore(0x20, _accessTokenUsed.slot) + let accessTokenSlot := keccak256(0, 0x40) + + // Revert if the access token is used. Equivalent to: + // if (_accessTokenUsed[accessTokenHash]) { + // revert AccessTokenUsed(); + // } + if sload(accessTokenSlot) { + mstore(0, AccessTokenUsed_selector) + revert(0x1c, 0x04) + } + + // Write the function selector for `AccessTokenVerifier.verify` + mstore(ptr, Verify_functionSelector) + // Write the calldata offset for the `Token` struct + mstore(add(ptr, Verify_token_head_offset), Verify_token_head_value) + // Write the calldata offset for the `FunctionCall` struct + mstore(add(ptr, Verify_functionCall_head_offset), Verify_functionCall_head_value) + // Copy the function selector of the current call to `token.functionCall.functionSignature` + calldatacopy(add(ptr, Verify_functionSignature_offset), 0x00, 0x04) + // Write the target and caller addresses to the `FunctionCall` struct. + mstore(add(ptr, Verify_target_offset), address()) + mstore(add(ptr, Verify_caller_offset), caller()) + + // Write the calldata offset to the `FunctionCall.parameters` field + mstore(add(ptr, Verify_parameters_head_offset), Verify_parameters_head_value) + + // Calculate the length of the function parameters of the current call, excluding + // the function selector and access token. + let parametersLength := sub(calldatasize(), AccessTokenAndSelectorPrefixSize) + // Write `token.functionCall.parameters.length` + mstore(add(ptr, Verify_parameters_length_offset), parametersLength) + // Copy the function parameters of the current call to `token.functionCall.parameters` + calldatacopy(add(ptr, Verify_parameters_data_offset), AccessTokenAndSelectorPrefixSize, parametersLength) + + // Calculate the size of the encoded calldata, which depends on the size of the input parameters + let verifyCalldataSize := add(Verify_parameters_data_offset, parametersLength) + + // Call `AccessTokenVerifier.verify` with the encoded calldata and bubble up revert data + // if the call fails. + if iszero(staticcall(gas(), verifierAddress, ptr, verifyCalldataSize, 0, 0x20)) { + returndatacopy(0, 0, returndatasize()) + revert(0, returndatasize()) + } + + // If the call returned invalid returndata (not 32 bytes) or something other + // than a single non-zero word, revert with the `VerificationFailed` selector. + // Equivalent to: + // if (!verifier.verify(...)) { + // revert VerificationFailed(); + // } + if iszero( + and( + eq(returndatasize(), 0x20), // Ensure contract returns 32 bytes + mload(0) // Ensure contract returns value with last bit set + ) + ) { + mstore(0x00, VerificationFailed_selector) + revert(0x1c, 0x04) + } + + // Zero out all of the memory used for the calldata to avoid dirty bits in inheriting contract. + calldatacopy(ptr, calldatasize(), verifyCalldataSize) + + // Mark the access token as used. Equivalent to: + // `_accessTokenUsed[accessTokenHash] = true;` + sstore(accessTokenSlot, 1) + } + } +} diff --git a/contracts/examples/DummyDapp.sol b/contracts/examples/DummyDapp.sol index f94038e..2aebd5c 100644 --- a/contracts/examples/DummyDapp.sol +++ b/contracts/examples/DummyDapp.sol @@ -23,7 +23,7 @@ contract DummyDapp is AccessTokenConsumer { uint256 expiry, address, uint256 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } } diff --git a/contracts/examples/DummyDappUpgradeable.sol b/contracts/examples/DummyDappUpgradeable.sol index da737c1..d1276f2 100644 --- a/contracts/examples/DummyDappUpgradeable.sol +++ b/contracts/examples/DummyDappUpgradeable.sol @@ -26,7 +26,7 @@ contract DummyDappUpgradeable is Initializable, OwnableUpgradeable, UUPSUpgradea uint256 expiry, address, uint256 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } } diff --git a/contracts/mocks/ConsumerMock.sol b/contracts/mocks/ConsumerMock.sol index bfc5e6d..bee0f02 100644 --- a/contracts/mocks/ConsumerMock.sol +++ b/contracts/mocks/ConsumerMock.sol @@ -12,7 +12,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes32 r, bytes32 s, uint256 expiry - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -22,7 +22,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes32 s, uint256 expiry, address - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -32,7 +32,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes32 s, uint256 expiry, uint256 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -42,7 +42,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes32 s, uint256 expiry, string calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -52,7 +52,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes32 s, uint256 expiry, string memory - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -62,7 +62,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes32 s, uint256 expiry, bytes1 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -72,7 +72,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes32 s, uint256 expiry, bytes calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -82,7 +82,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes32 s, uint256 expiry, bytes memory - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -93,7 +93,7 @@ contract ConsumerMock is AccessTokenConsumer { uint256 expiry, address, uint256 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -104,7 +104,7 @@ contract ConsumerMock is AccessTokenConsumer { uint256 expiry, uint256, string memory - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -115,7 +115,7 @@ contract ConsumerMock is AccessTokenConsumer { uint256 expiry, string calldata, bytes calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -126,7 +126,7 @@ contract ConsumerMock is AccessTokenConsumer { uint256 expiry, string calldata, bytes calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -138,7 +138,7 @@ contract ConsumerMock is AccessTokenConsumer { string calldata, bytes calldata, address - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -151,7 +151,7 @@ contract ConsumerMock is AccessTokenConsumer { bytes calldata, address, uint256 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -165,7 +165,7 @@ contract ConsumerMock is AccessTokenConsumer { address, uint256, bytes calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } } diff --git a/contracts/mocks/UpgradeableConsumerMock.sol b/contracts/mocks/UpgradeableConsumerMock.sol index 6133b29..3ce1189 100644 --- a/contracts/mocks/UpgradeableConsumerMock.sol +++ b/contracts/mocks/UpgradeableConsumerMock.sol @@ -13,7 +13,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes32 r, bytes32 s, uint256 expiry - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -23,7 +23,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes32 s, uint256 expiry, address - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -33,7 +33,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes32 s, uint256 expiry, uint256 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -43,7 +43,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes32 s, uint256 expiry, string calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -53,7 +53,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes32 s, uint256 expiry, string memory - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -63,7 +63,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes32 s, uint256 expiry, bytes1 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -73,7 +73,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes32 s, uint256 expiry, bytes calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -83,7 +83,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes32 s, uint256 expiry, bytes memory - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -94,7 +94,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { uint256 expiry, address, uint256 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -105,7 +105,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { uint256 expiry, uint256, string memory - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -116,7 +116,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { uint256 expiry, string calldata, bytes calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -127,7 +127,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { uint256 expiry, string calldata, bytes calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -139,7 +139,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { string calldata, bytes calldata, address - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -152,7 +152,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { bytes calldata, address, uint256 - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } @@ -166,7 +166,7 @@ contract UpgradeableConsumerMock is AccessTokenConsumerUpgradeable { address, uint256, bytes calldata - ) public requiresAuth(v, r, s, expiry) returns (bool) { + ) public requiresAuth returns (bool) { return true; } } diff --git a/contracts/upgradeable/AccessTokenConsumerUpgradeable.sol b/contracts/upgradeable/AccessTokenConsumerUpgradeable.sol index dedfec4..76b4d5f 100644 --- a/contracts/upgradeable/AccessTokenConsumerUpgradeable.sol +++ b/contracts/upgradeable/AccessTokenConsumerUpgradeable.sol @@ -2,7 +2,8 @@ pragma solidity >=0.8.13; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { IAccessTokenVerifier, AccessToken, FunctionCall } from "../interfaces/IAccessTokenVerifier.sol"; +import { IAccessTokenVerifier } from "../interfaces/IAccessTokenVerifier.sol"; +import { LibAccessTokenConsumer } from "../LibAccessTokenConsumer.sol"; /** * @title AccessTokenConsumerUpgradeable @@ -21,6 +22,9 @@ contract AccessTokenConsumerUpgradeable is Initializable { // Stores whether an EAT has already been used mapping(bytes32 => bool) private _accessTokenUsed; + error VerificationFailed(); + error AccessTokenUsed(); + /** * @dev Initializes the AcessTokenConsumer by setting the AccessTokenVerifier address. * This must be called in the initializer function of contracts inheriting AccessTokenConsumer. @@ -36,15 +40,8 @@ contract AccessTokenConsumerUpgradeable is Initializable { * by requiring a valid EAT to be provided. * If valid, it marks the EAT as consumed. */ - modifier requiresAuth( - uint8 v, - bytes32 r, - bytes32 s, - uint256 expiry - ) { - // VF -> Verification Failure - require(verify(v, r, s, expiry), "AccessToken: VF"); - _consumeAccessToken(v, r, s, expiry); + modifier requiresAuth() { + LibAccessTokenConsumer.consumeAccessToken(_accessTokenUsed, address(verifier)); _; } @@ -54,75 +51,4 @@ contract AccessTokenConsumerUpgradeable is Initializable { function setVerifier(address newVerifier) internal { verifier = IAccessTokenVerifier(newVerifier); } - - /** - * @dev Verifies an EAT by calling the AccessTokenVerifier. - * Reverts if the EAT has already been used. - */ - function verify(uint8 v, bytes32 r, bytes32 s, uint256 expiry) internal view returns (bool) { - // AU -> Already Used - require(!_isAccessTokenUsed(v, r, s, expiry), "AccessToken: AU"); - - AccessToken memory token = constructToken(expiry); - return verifier.verify(token, v, r, s); - } - - /** - * @dev Reconstructs an EAT based on `expiry` and current function call - * to populate function signature, target contract address, caller and function parameters. - */ - function constructToken(uint256 expiry) internal view returns (AccessToken memory token) { - FunctionCall memory functionCall; - functionCall.functionSignature = msg.sig; - functionCall.target = address(this); - functionCall.caller = msg.sender; - - functionCall.parameters = extractInputs(); - token.functionCall = functionCall; - token.expiry = expiry; - } - - /** - * @dev Takes calldata and extracts non-signature, non-expiry function inputs as a byte array - * Removes all references to the proof object except any offsets related to - * other inputs that are pushed by the proof - */ - function extractInputs() public pure returns (bytes memory inputs) { - // solhint-disable-next-line no-inline-assembly - assembly { - let ptr := mload(0x40) - calldatacopy(ptr, 0, calldatasize()) - mstore(0x40, add(ptr, calldatasize())) - - let startPos := 0x04 - let endOfSigExp := add(startPos, 0x80) - let totalInputSize := sub(calldatasize(), endOfSigExp) - - // Overwrite data to calldata pointer - inputs := ptr - - // Store expected length of total byte array as first value - mstore(inputs, totalInputSize) - - // Copy bytes from end of signature and expiry section to end of calldata - calldatacopy(add(inputs, 0x20), endOfSigExp, totalInputSize) - } - } - - /** - * @dev Returns whether an EAT has already been used. - */ - function _isAccessTokenUsed(uint8 v, bytes32 r, bytes32 s, uint256 expiry) internal view returns (bool) { - bytes32 accessTokenHash = keccak256(abi.encodePacked(v, r, s, expiry)); - return _accessTokenUsed[accessTokenHash]; - } - - /** - * @dev Marks an EAT as consumed/used. - */ - function _consumeAccessToken(uint8 v, bytes32 r, bytes32 s, uint256 expiry) private { - bytes32 accessTokenHash = keccak256(abi.encodePacked(v, r, s, expiry)); - - _accessTokenUsed[accessTokenHash] = true; - } } diff --git a/hardhat.config.ts b/hardhat.config.ts index c7dd2bb..3bab8ea 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -5,6 +5,7 @@ import "@typechain/hardhat"; import "hardhat-gas-reporter"; import "solidity-coverage"; import "hardhat-contract-sizer"; +import "hardhat-gas-reporter"; import "@openzeppelin/hardhat-upgrades"; import "./tasks"; @@ -166,8 +167,9 @@ const config: HardhatUserConfig = { tests: "./test", }, solidity: { - version: "0.8.13", + version: "0.8.24", settings: { + viaIR: true, metadata: { // Not including the metadata hash // https://github.com/paulrberg/solidity-template/issues/31 diff --git a/test/AccessTokenConsumerSuite/AccessTokenConsumer.behaviour.ts b/test/AccessTokenConsumerSuite/AccessTokenConsumer.behaviour.ts index ccb9cb9..fc84fd0 100644 --- a/test/AccessTokenConsumerSuite/AccessTokenConsumer.behaviour.ts +++ b/test/AccessTokenConsumerSuite/AccessTokenConsumer.behaviour.ts @@ -341,7 +341,7 @@ const performTestSuiteForFunction = async ( contract .connect(extraAccounts[0]) [functionName](this.signature.v, this.signature.r, this.signature.s, this.token.expiry, ...parameters), - ).to.be.revertedWith("AccessToken: VF"); + ).to.be.revertedWith("VerificationFailed"); }); it("with expired token should revert", async function () { @@ -370,7 +370,7 @@ const performTestSuiteForFunction = async ( this.token.expiry.add(50), ...parameters, ), - ).to.be.revertedWith("AccessToken: VF"); + ).to.be.revertedWith("VerificationFailed"); }); it("with used EAT should revert", async function () { @@ -380,7 +380,7 @@ const performTestSuiteForFunction = async ( await expect( contract[functionName](this.signature.v, this.signature.r, this.signature.s, this.token.expiry, ...parameters), - ).to.be.revertedWith("AccessToken: AU"); + ).to.be.revertedWith("AccessTokenUsed"); }); it("with incorrect signer should revert", async function () { @@ -388,7 +388,7 @@ const performTestSuiteForFunction = async ( await expect( contract[functionName](signature.v, signature.r, signature.s, this.token.expiry, ...parameters), - ).to.be.revertedWith("AccessToken: VF"); + ).to.be.revertedWith("VerificationFailed"); }); it("with incorrect function signature should revert", async function () { @@ -404,13 +404,13 @@ const performTestSuiteForFunction = async ( await expect( contract[functionName](signature.v, signature.r, signature.s, this.token.expiry, ...parameters), - ).to.be.revertedWith("AccessToken: VF"); + ).to.be.revertedWith("VerificationFailed"); }); it("with incorrect target contract should revert", async function () { await expect( fakeMock[functionName](this.signature.v, this.signature.r, this.signature.s, this.token.expiry, ...parameters), - ).to.be.revertedWith("AccessToken: VF"); + ).to.be.revertedWith("VerificationFailed"); }); }); };