Author: Vadim Fadeev - Rarible
Reviewer: Anna Riabokon - Rari Foundation
1. Abstract
This proposal upgrades the Rarible ExchangeV2 order validation logic to fully support Account Abstraction (AA) and smart contract wallets while remaining backward compatible with existing EOAs and signatures.
The new implementation:
- Uses EIP-712 typed data (
"Exchange", "2") for deterministic order hashing. - Adds robust EIP-1271 signature verification for contract-based accounts (AA wallets, Safes, etc.).
- Retains standard ECDSA validation for EOAs.
- Avoids incorrect assumptions based on
EXTCODESIZE: AA wallets are contracts and therefore have non-zero code size, but must still be treated as valid signers when compliant with EIP-1271.
This change is implemented via an upgrade of the ExchangeV2 order validation component and executed on-chain through Tally’s executable proposal mechanism.
2. Motivation
2.1 Account Abstraction Compatibility
Modern users increasingly interact through smart contract wallets / AA accounts (e.g. Safe, AA frameworks, modular wallets). These are deployed as contracts, so EXTCODESIZE (and equivalents) returns non-zero, even when they function as primary user wallets.
Legacy patterns that interpret “contract = invalid user” or require EXTCODESIZE == 0 for signature validity break AA flows.
This upgrade:
- Explicitly supports contract-based accounts as order makers.
- Verifies their signatures using EIP-1271 (
isValidSignature) instead of rejecting or misclassifying them. - Ensures AA users can seamlessly create, sign, and execute orders on Rarible Protocol.
2.2 Security & Correctness
- Uses structured EIP-712 hashing via
EIP712Upgradeablefor robust domain separation. - Separates EOAs and contracts using standard introspection, but does not rely on
EXTCODESIZE == 0as a trust signal. - Prevents false negatives for valid AA wallets and reduces attack surface caused by ad hoc signature handling.
2.3 Ecosystem Alignment
- Aligns Rarible ExchangeV2 with ecosystem standards around:
- EIP-1271 for contract wallet signatures.
- Account abstraction–friendly infra across major wallets and bundlers.
- Simplifies integrations for partners that already support AA and contract wallets.
3. Rationale
The Rarible Protocol must remain compatible with:
- EOAs signing EIP-712 orders.
- Smart contract wallets implementing EIP-1271.
- Future AA patterns that standardize contract-based authentication.
The proposed model:
- Uses a single canonical EIP-712 hash (
LibOrder.hash+_hashTypedDataV4) as the message to verify. - For contracts: calls
isValidSignatureand expects the magic value0x1626ba7e. - For EOAs: uses ECDSA recovery and strict equality to
order.maker. - Ensures
order.maker != address(0)on all accepted paths. - Does not assume that non-zero code size implies invalidity; instead, it implies EIP-1271 verification is required.
This keeps the design simple, auditable, and compatible with both existing users and AA-native flows.
4. Specifications
4.1 Validation Logic (High-Level)
Given order (LibOrder.Order) and signature:
- Compute:
hash = LibOrder.hash(order)typedHash = _hashTypedDataV4(hash)
- If
order.salt == 0andorder.maker != address(0):- Require
msg.sender == order.maker. - No off-chain signature check required (gas-efficient path).
- Require
- Otherwise, if
msg.sender != order.maker:- If
order.makeris a contract:- Call
IERC1271(order.maker).isValidSignature(typedHash, signature). - Require returned value equals
0x1626ba7e(MAGICVALUE). - If the call reverts or returns anything else, revert with a clear error.
- Call
- If
order.makeris not a contract:- Recover signer from
typedHashusing ECDSA. - Require recovered signer equals
order.maker.
- Recover signer from
- If
- In all valid flows:
- Require
order.maker != address(0).
- Require
- Maintain storage gap for upgradeable compatibility.
4.2 Reference Implementation Snippet
// SPDX-License-Identifier: MIT
pragma solidity 0.7.6;
import "./libraries/LibOrder.sol";
import "@rarible/lib-signature/contracts/IERC1271.sol";
import "@rarible/lib-signature/contracts/LibSignature.sol";
import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/drafts/EIP712Upgradeable.sol";
abstract contract OrderValidator is Initializable, ContextUpgradeable, EIP712Upgradeable {
using LibSignature for bytes32;
using AddressUpgradeable for address;
bytes4 constant internal MAGICVALUE = 0x1626ba7e;
function __OrderValidator_init_unchained() internal initializer {
__EIP712_init_unchained("Exchange", "2");
}
function validate(LibOrder.Order memory order, bytes memory signature) internal view {
if (order.salt == 0) {
if (order.maker != address(0)) {
require(_msgSender() == order.maker, "maker is not tx sender");
}
} else {
if (_msgSender() != order.maker) {
bytes32 hash = LibOrder.hash(order);
bytes32 typedHash = _hashTypedDataV4(hash);
if (order.maker.isContract()) {
bool isValid = false;
// AA / smart contract wallet: EIP-1271
try IERC1271(order.maker).isValidSignature(typedHash, signature) returns (bytes4 result) {
isValid = (result == MAGICVALUE);
} catch {
isValid = false;
}
require(isValid, "contract order signature verification error");
require(order.maker != address(0), "no maker");
} else {
// EOA: ECDSA
address signer = typedHash.recover(signature);
require(signer == order.maker, "order signature verification error");
require(order.maker != address(0), "no maker");
}
}
}
}
uint256[50] private __gap;
}
Note: For AA wallets and smart contract wallets, EXTCODESIZE(order.maker) (or order.maker.code.length) is non-zero, which is expected and supported. These accounts are validated exclusively via EIP-1271, not rejected because they are contracts.
5. Steps to Implement
-
Specification & Feedback
- Publish this proposal to the RARI DAO forum for comments from the community, wallet teams, and integrators.
-
Testing & Audit
- Extend test suite to cover:
- EOAs with valid/invalid signatures.
- EIP-1271-compliant wallets (e.g. Safe).
- AA flows where maker is a contract with non-zero code size.
- Optionally commission an external review focused on the new validation path.
- Extend test suite to cover:
-
On-Chain Proposal
- Deploy an upgrade contract or use existing upgrade mechanisms.
- Create a Tally proposal with executable calldata to:
- Upgrade ExchangeV2 implementation to the new
OrderValidatorlogic.
- Upgrade ExchangeV2 implementation to the new
-
Governance Process
- Voting period (~5 days, per DAO rules).
- Cooldown/veto period (~2 days), if applicable.
-
Execution
- Upon approval, execute the upgrade via Tally.
- New validation logic becomes effective for all new orders.
- Communicate upgrade details to integrators and ecosystem partners.
6. Summary
This proposal upgrades Rarible ExchangeV2 to be Account Abstraction–ready by:
- Supporting EIP-1271 signatures for smart contract wallets.
- Preserving EOA support via ECDSA + EIP-712.
- Correctly handling the fact that AA wallets are contracts with non-zero
EXTCODESIZE, and must be validated via contract-based logic instead of being implicitly disqualified.
The change is minimal in scope, high in impact, and fully aligned with the evolving Ethereum wallet landscape, ensuring Rarible remains a secure, modern, and AA-compatible protocol.