Technical Documentation
Lockx provides an end-to-end security system to manage and secure Ethereum assets through smart contract powered Lockboxes that can store ETH, ERC20 tokens, and ERC721 NFTs. Lockx provides various key management options to secure your Lockbox, with options to use your own personal signing key or our proprietary key fraction technology that enables you to create keys based off of your existing wallet to reduce the burden of needing to manage additional keys.
Our documentation provides comprehensive technical details about our smart contracts, key fraction technology, and security benefits.
Smart Contracts
Contract Overview
The Lockx platform is built on a minimalist suite of just four Solidity smart contracts with a clear separation of concerns. This intentionally simple architecture focuses solely on securely depositing and withdrawing assets from NFTs.
Lockx Contract
The main NFT contract that implements ERC-721 functionality and soulbound token properties (EIP-5192). This is the only concrete contract users interact with directly for minting.
Withdrawals Contract
Abstract contract that inherits from Deposits and adds signature-gated withdrawal functionality. All withdrawal operations require cryptographic authorization.
Deposits Contract
Abstract contract that handles all deposit operations for ETH, ERC20 tokens, and ERC721 NFTs. It maintains the storage structure and provides deposit functionalities.
Signature Verification
The security foundation that implements EIP-712 typed signature verification. All withdrawal operations rely on this to securely authorize asset movements.
Intentional Simplicity
Lockx employs a deliberately simple architecture with just four contracts. Each contract has a single, well-defined purpose: Lockx handles NFT functionality, Deposits manages asset storage, Withdrawals handles asset retrieval, and SignatureVerification provides secure authorization. This minimalist approach makes the code easier to audit and reduces attack surfaces.
Contract Inheritance Structure
Lockx ├── ERC721 │ └── IERC721 ├── Ownable ├── Withdrawals (abstract) │ └── Deposits (abstract) │ ├── SignatureVerification │ │ └── EIP712 │ ├── IERC721Receiver │ └── ReentrancyGuard └── IERC5192 (Soulbound interface)
The inheritance diagram shows how the four contracts work together in a linear hierarchy. Deposits inherits from SignatureVerification, IERC721Receiver, and ReentrancyGuard. Withdrawals inherits from Deposits, and Lockx inherits from ERC721, Ownable, Withdrawals, and IERC5192. This creates a clean separation of concerns while maintaining a simple inheritance path.
Key Management
Key Fraction Technology
Lockx implements a unique key fraction technology that enhances security through a multi-party computation approach to key generation and management. This technology ensures private keys are never stored in their entirety—instead, they're deterministically derived when needed through a secure process.
Zero Trust Architecture
Our key fraction technology implements zero trust principles. Lockx never stores complete private keys—not even temporarily. Keys are derived on-demand and immediately deleted from memory after use.
How Key Fraction Technology Works
User Authentication: You sign a unique message that includes a random "message key fraction" generated for your session.
Server-Side Key Fraction: Lockx generates a random key fraction that's encrypted and stored securely in Google Cloud KMS (Key Management Service). This is protected by Hardware Security Modules (HSM) with FIPS level 3 compliance for enterprise-grade security.
Ephemeral Key Derivation: When needed, your signature is combined with the server-side key fraction to deterministically derive the public/private key pair through a cryptographic hash function. This creates a unique, one-time-use signing key that exists only for the duration of the specific operation.
Expiring Signatures: All generated signatures have a short lifespan and include operation-specific data that prevents them from being reused for other purposes. This time-bound approach provides enhanced security by limiting the window of opportunity for potential attacks.
Immediate Cleanup: After the operation is completed, the derived private key is immediately removed from memory. Keys must be rederived for every operation, ensuring no persistent key material exists that could be compromised.
Security Benefits
- No complete private key is ever stored anywhere
- Both user input (signature) and server-side fraction are required to derive the key
- Server-side key fractions are encrypted at rest
- Advanced plan users benefit from HSM protection for their key fractions
- Key rotation supported for enhanced security
Key Export & Recovery
Lockx provides you with the encrypted key fraction during setup, which you can securely store as a backup. This fraction is essential for key recovery and export:
Key Export Process
- When you need to export your private key, you'll need to provide:
- Your wallet signature
- The encrypted key fraction you received during setup
- Valid 2FA code as proof of ownership
- Once verified, Lockx temporarily reconstructs your private key for export
- The key is securely delivered to you and immediately purged from our systems
Key Ownership
Even though Lockx manages the key fraction technology, you always maintain ultimate ownership of your keys. You can export your complete key details whenever needed by proving ownership through our verification process.
2FA Protection
Lockx implements robust 2FA (Two-Factor Authentication) protection using the same trustless key derivation approach:
Trustless TOTP Management
- Lockx creates TOTP (Time-based One-Time Password) secrets using the same trustless key derivation process used for Lockx key fractions
- Like key fractions, TOTP secrets are never stored in their complete form anywhere
- The 2FA code is required to decrypt associated Lockx key fractions and export them
- Unlike traditional web2 systems, Lockx doesn't store any TOTP secrets - they are trustlessly derived on-demand
- We verify the code against your authentication application to guarantee security
Compatible Applications
Lockx 2FA is compatible with industry-standard authenticator applications:
Self Custody Signing
For users who prefer complete control, Lockx offers a self custody option where you manage both key fractions:
Self Custody Mode Features
- Complete Control: You receive both key fractions and manage them independently
- No Server Dependency: Your assets remain accessible even if Lockx services are unavailable
- Enhanced Privacy: You can sign operations locally without connecting to Lockx servers
- Higher Security: For advanced users, this mode provides the strongest security model
Important Security Notice
Self custody mode offers the highest security but requires diligent key management. Loss of your key fractions may result in permanent loss of access to your assets. Always maintain secure backups of your key fractions.
When choosing self custody mode, you'll receive detailed instructions for securely backing up and using your key fractions. This option is ideal for advanced users familiar with private key management best practices.
Key Rotation
To maintain the highest level of security, Lockx supports key rotation, allowing you to update your signing keys without affecting your assets. This feature is essential for:
- Regular security maintenance (recommended every 6-12 months)
- Responding to potential security incidents
- Updating keys after changes to your security setup
- Migrating to a new security model
Key Rotation Process
- Navigate to the key management section in your account
- Authenticate using your current wallet and 2FA
- Follow the guided process to generate new key fractions
- Confirm the update after verifying new key functionality
- Previous keys are deactivated and can no longer be used for operations
Key rotation preserves all your assets and settings while updating only the underlying signing keys. This process can be completed in minutes and provides significant security benefits with minimal disruption.
Lockbox
Secure Asset Storage
Lockboxes function as secure digital safe deposit boxes in your wallet, with direct 1:1 mapping of deposited assets to the specific Lockbox. Each asset is precisely mapped to its owner's NFT through a secure token ID system, with exact precision maintained for all asset types.
Direct Asset Mapping
Every Lockbox maintains precise mappings between the tokenId and deposited assets using secure on-chain storage structures:
mapping(uint256 => uint256) internal _baggedETH;
mapping(uint256 => mapping(address => uint256)) internal _erc20Balances;
mapping(uint256 => address[]) internal _erc20TokenAddresses;
mapping(uint256 => mapping(address => bool)) internal _erc20Known;
struct BaggedNFT { address nftContract; uint256 nftTokenId; }
mapping(uint256 => bytes32[]) internal _nftKeys;
mapping(uint256 => mapping(bytes32 => BaggedNFT)) internal _nftData;
mapping(uint256 => mapping(bytes32 => bool)) internal _nftKnown;
These storage structures ensure that each asset is linked directly to a specific Lockbox token ID, creating a secure 1:1 relationship between your NFT and the assets it contains.
Your Assets, Your Control
Lockx contracts have no administrator backdoors, privileged roles, or built-in methods to access user funds. The contract has no "admin functions" that can drain liquidity, pause withdrawals, or modify balances. Your assets remain securely mapped to your NFT with no external control mechanisms.
Zero Fee Structure
There are no built-in smart contract fees or costs for minting, deposits, or withdrawals, with no interaction fees, arbitrary deposit or withdrawal limits, tokenomics, upgradeability, or liquidity-draining functions. Your Lockx NFT—and the assets it holds—always remains mapped to the wallet it is bound to, giving you continuous access to your funds even if the Lockx interface or web app becomes unavailable.
Maximum Precision Guarantees
ETH Precision
ETH balances are stored in full wei precision (1018 units per ETH), ensuring exact accounting down to the smallest unit of ether:
function _depositETH(uint256 tokenId, uint256 amountETH) internal {
if (amountETH == 0) return;
_baggedETH[tokenId] += amountETH;
}
ERC20 Token Precision with Delta Tracking
ERC20 token balances maintain the token's native decimal precision with an advanced delta-based tracking system that guarantees the exact amount received is what gets recorded:
function _depositERC20(
uint256 tokenId,
address tokenAddress,
uint256 amount
) internal {
IERC20 t = IERC20(tokenAddress);
if (!_erc20Known[tokenId][tokenAddress]) {
_erc20TokenAddresses[tokenId].push(tokenAddress);
_erc20Known[tokenId][tokenAddress] = true;
}
uint256 beforeBal = t.balanceOf(address(this));
t.safeTransferFrom(msg.sender, address(this), amount);
uint256 afterBal = t.balanceOf(address(this));
uint256 delta = afterBal > beforeBal ? afterBal - beforeBal : 0;
if (delta == 0) revert ZeroAmount();
_erc20Balances[tokenId][tokenAddress] += delta;
}
Enhanced precision: Instead of directly adding the requested amount, our contracts measure the actual token balance change (delta) before and after the transfer. This guarantees that the exact amount received is what gets recorded, providing protection against tokens with transfer fees, rebasing mechanisms, or other non-standard behaviors. The contract now also explicitly verifies that tokens were actually received by checking for a non-zero delta.
Viewing Your Lockbox Contents
The contract provides a comprehensive view function that allows only you, the valid Lockbox owner, to see all assets contained in your Lockbox:
function getFullLockbox(uint256 tokenId) external view returns ( uint256 bagETH, BaggedERC20[] memory erc20Tokens, BaggedNFT[] memory nfts ) { _requireExists(tokenId); if (_erc721.ownerOf(tokenId) != msg.sender) revert NotOwner(); bagETH = _baggedETH[tokenId]; address[] storage tokenAddresses = _erc20TokenAddresses[tokenId]; erc20Tokens = new BaggedERC20[](tokenAddresses.length); for (uint256 i; i < tokenAddresses.length; ) { address tokenAddr = tokenAddresses[i]; uint256 bal = _erc20Balances[tokenId][tokenAddr]; erc20Tokens[i] = BaggedERC20(tokenAddr, bal); unchecked { ++i; } } }
Gas optimizations
The contract includes numerous gas optimizations to minimize transaction costs:
- Simplified ETH storage: Using a direct uint256 mapping for ETH balances instead of a struct reduces gas costs
- Unchecked increments: Loop counters use unchecked blocks where overflow is impossible, saving gas on increment operations
- Complete storage cleanup: When asset balances reach zero, all associated storage is deleted to earn gas refunds
- Swap and pop pattern: Efficient array item removal that maintains O(1) complexity instead of shifting elements
- Conditional safe minting: Uses regular _mint for EOA addresses and _safeMint only for contract recipients
- Minimal storage: Storage is carefully structured to minimize blockchain storage costs
function _removeERC20Token(uint256 tokenId, address tokenAddress) internal {
address[] storage tokenAddresses = _erc20TokenAddresses[tokenId];
uint256 len = tokenAddresses.length;
for (uint256 i; i < len; ) {
if (tokenAddresses[i] == tokenAddress) {
tokenAddresses[i] = tokenAddresses[len - 1];
tokenAddresses.pop();
break;
}
unchecked { ++i; }
}
}
Soulbound Nature
Lockboxes are "soulbound" to the wallet they are minted to, meaning they cannot be transferred to other wallets. This crucial security feature ensures your assets remain safely within your ownership and cannot be stolen or transferred away.
EIP-5192 Standard Implementation
What is EIP-5192? EIP-5192 is the Ethereum Improvement Proposal that standardizes "soulbound" or non-transferable tokens. This standard allows applications to easily identify which NFTs are permanently bound to their current owner.Read the EIP-5192 specification
The Lockx contract implements the EIP-5192 standard through the IERC5192 interface:
interface IERC5192 {
/// Emitted exactly once when a token becomes locked (non-transferable).
event Locked(uint256 tokenId);
/// Emitted if a token ever becomes unlocked (not used, but must be declared for compliance).
event Unlocked(uint256 tokenId);
/// MUST always return true for every existing Lockbox.
function locked(uint256 tokenId) external view returns (bool);
}
When a Lockbox is minted, it's immediately marked as locked and an EIP-5192 Locked
event is emitted:
uint256 tokenId = _tokenIdCounter.current();
_tokenIdCounter.increment();
_safeMint(to, tokenId);
emit Locked(tokenId);
initialize(tokenId, lockxPublicKey);
Transfer Prevention
The core of the soulbound mechanism is the overridden _transfer
function, which prevents any transfers of Lockboxes:
/// Disable any transfer—soul‐bound enforcement. function _transfer(address, address, uint256) internal pure override { revert TransfersDisabled(); }
This simple but powerful override ensures that no standard transfer function can move a Lockbox from its original owner's wallet. All transfer attempts will immediately revert with a TransfersDisabled
error.
The contract also implements the required locked
function, which confirms that a token is non-transferrable:
/** * @notice Always returns true for existing Lockboxes (soul‐bound). * @param tokenId The ID of the Lockbox. * @return Always true. * @dev Reverts if token does not exist. */ function locked(uint256 tokenId) external view override returns (bool) { if (!_exists(tokenId)) revert NonexistentToken(); return true; }
Interface Detection
To ensure applications can detect that Lockboxes implement the EIP-5192 soulbound standard, the contract includes the interface detection method:
function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) { if (interfaceId == 0xb45a3c0e) return true; return super.supportsInterface(interfaceId); }
This enables wallets, marketplaces, and other applications to detect and appropriately handle the soulbound nature of Lockboxes.
Marketplace Protection
The soulbound nature prevents Lockboxes from being listed or sold on NFT marketplaces. Unlike regular NFTs, your Lockbox cannot be accidentally listed for sale or transferred to another wallet, ensuring your assets remain securely in your control.
Theft Prevention
Even if your wallet's private key is compromised, an attacker cannot transfer your Lockbox to another wallet. This provides an additional layer of security beyond standard NFTs, as the attacker would also need your Lockx signing key to access the assets within your bag.
Why Soulbound Matters
The soulbound property creates a fundamental security improvement by:
- Preventing social engineering attacks that trick users into transferring NFTs
- Eliminating the risk of approvals that could allow third parties to move your NFT
- Creating a permanent bond between your wallet and your Create new Lockbox
- Requiring both wallet access AND signature verification for any asset withdrawals
- Ensuring your assets remain accessible even if marketplaces or frontends go offline
Multi-Asset Support
Lockboxes are designed to securely hold multiple types of digital assets simultaneously within a single NFT. This creates a unified "digital safe deposit box" for your assets, all represented in your wallet as one NFT.
Supported Asset Types
ETH
Native ETH with full wei precision (10^18)
ERC20 Tokens
Any ERC20-compatible token with native precision
NFTs (ERC721)
Individual NFTs can be stored inside your Lockbox
All these asset types can be stored within a single Lockbox, creating a consolidated view of your digital assets in one place.
Batch Management
Lockx allows for efficient batch operations, enabling you to deposit or withdraw multiple assets in a single transaction. This significantly reduces gas costs and simplifies asset management.
Batch deposit operations
The batch deposit function allows simultaneous deposit of ETH, ERC20 tokens, and NFTs with a single transaction. Here's how the contract handles different asset types:
function batchDeposit(
uint256 tokenId,
uint256 amountETH,
address[] calldata tokenAddresses,
uint256[] calldata tokenAmounts,
address[] calldata nftContracts,
uint256[] calldata nftTokenIds,
bytes32 referenceId
) external payable nonReentrant {
_requireOwnsBag(tokenId);
if (msg.value != amountETH) revert ETHMismatch();
_batchDeposit(tokenId, amountETH, tokenAddresses, tokenAmounts, nftContracts, nftTokenIds, referenceId);
}
function _batchDeposit(
uint256 tokenId,
uint256 amountETH,
address[] calldata tokenAddresses,
uint256[] calldata tokenAmounts,
address[] calldata nftContracts,
uint256[] calldata nftTokenIds,
bytes32 referenceId
) internal {
if (tokenAddresses.length != tokenAmounts.length || nftContracts.length != nftTokenIds.length) revert MismatchedInputs();
if (amountETH > 0) _baggedETHs[tokenId].ethAmount += amountETH;
for (uint256 i; i < tokenAddresses.length; ) {
_depositERC20(tokenId, tokenAddresses[i], tokenAmounts[i], referenceId);
unchecked { ++i; }
}
for (uint256 i; i < nftContracts.length; ) {
_depositERC721(tokenId, nftContracts[i], nftTokenIds[i], referenceId);
unchecked { ++i; }
}
}
The batch deposit process intelligently verifies all inputs and then processes each asset type using the appropriate deposit method. Notice the use of unchecked
blocks for gas optimization in the loops.
Batch withdrawal operations
Similarly, the batch unbag function enables withdraw multiple assets in a single transaction, with just one signature verification. This is especially valuable for efficient portfolio management:
function batchUnbag(
uint256 tokenId,
bytes32 messageHash,
bytes memory signature,
uint256 amountETH,
address[] calldata tokenAddresses,
uint256[] calldata tokenAmounts,
address[] calldata nftContracts,
uint256[] calldata nftTokenIds,
address recipient,
bytes32 referenceId,
uint256 signatureExpiry
) external nonReentrant {
_requireOwnsBag(tokenId);
if (block.timestamp > signatureExpiry) revert SignatureExpired();
if (recipient == address(0)) revert ZeroAddress();
bytes memory data = abi.encode(
tokenId, amountETH, tokenAddresses, tokenAmounts,
nftContracts, nftTokenIds, recipient, referenceId,
msg.sender, signatureExpiry
);
verifySignature(tokenId, messageHash, signature, address(0), OperationType.BATCH_UNBAG, data);
if (amountETH > 0) {
if (_baggedETHs[tokenId].ethAmount < amountETH) revert InsufficientETH();
_baggedETHs[tokenId].ethAmount -= amountETH;
(bool success, ) = payable(recipient).call{value: amountETH}("");
if (!success) revert ETHTransferFailed();
}
emit Unbagged(tokenId, referenceId);
}
Key benefits of batch operations
The multi-asset batch operations provide several important advantages:
- Gas efficiency: Batch operations significantly reduce total gas costs compared to individual transactions
- Simplified management: Deposit or withdraw multiple assets with a single transaction
- Unified security: All operations are protected by the same signature verification process
- Asset diversity: Handle ETH, any ERC20 token, and any ERC721 NFT simultaneously
- Portfolio rebalancing: Easily adjust your Secured assets in a single transaction
- Optimized loops: Uses unchecked blocks for gas optimization in loops with array bounds guarantees
Gas optimization note
Due to current Ethereum gas transaction limits, we recommend limiting batch operations to no more than 3 different assets in a single transaction. Exceeding this number may approach block gas limits, especially when transferring multiple NFTs which require more complex storage operations.
Wallet Representation
Your Lockbox appears directly in your wallet, representing all contained assets. This provides a seamless user experience where all your stored assets are visible as a single NFT in your wallet, while still maintaining the highest security standards.
Security Benefits
Wallet Attack Protection
Lockboxes provide significant security benefits by using a separate signing key that's distinct from your wallet's private key. This architecture creates an additional security layer that protects your assets even if your wallet becomes compromised.
Defense Against Common Wallet Attacks
Attack Scenario: Wallet Private Key Compromise
Traditional Vulnerability: If an attacker obtains your wallet's private key, they typically gain complete control over all assets in that wallet.
Without Lockx Protection:
- Attacker can transfer all ETH and tokens
- Attacker can approve malicious contracts to spend tokens
- All NFTs can be immediately transferred away
With Lockx Protection:
- Attacker sees the Lockbox but cannot transfer it (soulbound)
- Cannot withdraw assets without the separate Lockx signing key
- All assets inside the bag remain secure
Security Mechanism: Lockx requires a separate signature from the Lockx key linked to your NFT for any asset withdrawal. Even with your wallet's private key, an attacker cannot generate valid signatures from your Lockx key.
Attack Scenario: Signature Phishing
Traditional Vulnerability: Attackers trick users into signing malicious transactions or permissions that drain their wallets or grant access to their assets.
Without Lockx Protection:
- One malicious signature can drain entire wallet
- Users often can't tell what they're signing
- Approvals may enable ongoing asset theft
With Lockx Protection:
- Assets in Lockx bags require specific EIP-712 signatures
- Phished wallet signatures cannot withdraw from bags
- Separate Lockx key is needed for withdrawals
Security Mechanism: The Lockx contract only accepts properly formatted EIP-712 signatures from the specific Lockx key associated with your NFT. Signatures from your wallet key alone are insufficient.
Attack Scenario: Seed Phrase Compromise
Traditional Vulnerability: If attackers obtain your wallet's seed phrase, they can recreate your wallet and gain full access to all assets.
Without Lockx Protection:
- Complete wallet takeover on any device
- All assets can be transferred immediately
- No secondary verification required
With Lockx Protection:
- Seed phrase doesn't reveal Lockx signing key
- Assets within bags remain secured
- Attacker would need access to both your wallet and Lockx key
Security Mechanism: Lockx keys are generated separately from your wallet and can be stored securely through our key fraction technology or Self custody options. A compromised seed phrase doesn't expose these keys.
Attack Scenario: Blind Signature Attacks
Traditional Vulnerability: Attackers trick users into signing messages with obscured or misleading contents, which are actually authorizations for asset transfers.
Without Lockx Protection:
- Users may sign messages without understanding implications
- Signatures might authorize unexpected operations
- Unclear what action is being authorized
With Lockx Protection:
- EIP-712 provides structured, human-readable data
- Operations specify exact amounts and recipients
- Two-key architecture requires both wallet and Lockx key signatures
Security Mechanism: Lockx uses EIP-712 typed data signatures that clearly display the operation being performed, including specific assets, amounts, and recipients. Additionally, the separation of wallet and Lockx keys provides protection even if one signature is compromised.
Attack Scenario: Malware and RAT Trojan Attacks
Traditional Vulnerability: Sophisticated trojans like StilachiRAT target cryptocurrency wallets to steal private keys and credentials from wallet extensions such as MetaMask.
Without Lockx Protection:
- Malware can extract keys from memory
- Private keys stored in browser extensions can be compromised
- Once extracted, all wallet assets are immediately at risk
With Lockx Protection:
- Lockx keys are ephemeral - never persistently stored
- Keys generated on-demand and immediately destroyed after use
- Compromised wallet doesn't expose assets inside soulbound NFT
Security Mechanism: Lockx protects against advanced malware by using ephemeral key technology. Even if trojans compromise your main wallet's private key, they cannot access assets inside your soulbound Lockbox since withdrawals require the secondary ephemeral key that's generated on-demand and immediately destroyed after use.
Attack Scenario: Wallet Drainers and Scam Sites
Traditional Vulnerability: Wallet drainer scams trick users into connecting their wallets to malicious websites that rapidly drain all assets through token approvals or direct transfers.
Without Lockx Protection:
- Entire wallet can be emptied instantly
- All approvals can be exploited
- Drainer scripts operate automatically
With Lockx Protection:
- Lockboxes are soulbound and cannot be transferred
- All withdrawals require separate EIP-712 signatures
- Contract interactions with Lockboxes are strictly limited
Security Mechanism: Lockboxes are soulbound and cannot be drained or transferred from the wallet they are bound to. All content inside requires a separate interaction with the Lockx smart contract, which requires a separate EIP-712 typed signature. All bagged assets remain secure inside the Lockbox.
Attack Scenario: Malicious Airdrops
Traditional Vulnerability: Attackers use malicious airdrops to send tokens with exploitative code that can drain wallets when users attempt to interact with the tokens.
Without Lockx Protection:
- Unexpected tokens appear in wallet
- Interacting with tokens triggers malicious code
- Can lead to approval exploits or wallet draining
With Lockx Protection:
- Lockboxes only accept deposits from the token owner
- No automatic token acceptance mechanism
- Malicious tokens remain outside the secure bag
Security Mechanism: Lockboxes only accept deposits from the token owner, so the contents cannot be compromised by malicious airdrops or random tokens. This provides an extra layer of security against increasingly common airdrop-based attack vectors.
Attack Scenario: Proprietary Wallet Infrastructure Risks
Traditional Vulnerability: Reliance on proprietary wallet infrastructure creates single points of failure, exposes users to vendor-specific risks, and may limit interoperability.
Without Lockx Protection:
- Vendor-specific security risks
- Service outages may restrict access to assets
- Limited wallet compatibility and migration options
With Lockx Protection:
- Works with any ERC-721 compatible wallet
- Simple dual-key multisignature system
- Open and accessible smart contract architecture
Security Mechanism: Unlike complex systems that rely on proprietary wallet infrastructure, Lockx assets are held inside a soulbound NFT adhering to the ERC-721 standard that any Ethereum Self custody wallet can own. The dual-key multisignature system is simple to interact with, and the smart contract is public and always accessible.
Contract Attack Protection
The Lockx smart contracts implement numerous security measures to protect against common attack vectors that target smart contracts. These protections ensure the integrity and security of the contract's operations.
Smart Contract Security Measures
Attack Scenario: Reentrancy Attacks
Vulnerability: In a reentrancy attack, a malicious contract calls back into the victim contract before the first invocation is complete, potentially manipulating state and draining assets.
function unbagETH( uint256 tokenId, bytes32 messageHash, bytes memory signature, uint256 amount, address recipient, bool burnToken, bytes32 referenceId ) public nonReentrant { }
Security Mechanism: All deposit and withdrawal functions in the Lockx contract use OpenZeppelin's nonReentrant
modifier, which prevents reentrancy attacks by using a mutex pattern. This ensures that a function cannot be re-entered before its first invocation completes.
Attack Scenario: Signature Replay Attacks
Vulnerability: In a replay attack, a valid signature is reused to execute the same operation multiple times, potentially draining assets repeatedly.
function verifySignature( uint256 tokenId, bytes32 messageHash, bytes memory signature, address newLockxPublicKey, OperationType opType, bytes memory data ) internal { tokenData.nonce++; }
Security Mechanism: Lockx incorporates a nonce-based signature verification system. Each signature includes the current nonce value, and after verification, the nonce is incremented. This prevents the same signature from being used twice, as the nonce value would no longer match.
Attack Scenario: Transaction Ordering Manipulation
Vulnerability: Attackers can observe pending transactions and insert their own transactions with higher gas prices to manipulate execution order for profit (front-running).
Traditional Risks:
- Front-running valuable transactions
- Sandwich attacks on swap transactions
- Racing to claim limited opportunities
Lockx Protection:
- All operations require unique signatures
- Operations are tied to specific recipients
- No shared pools that can be manipulated
Security Mechanism: Lockx uses a direct asset mapping approach where each operation is explicitly authorized for a specific recipient with an exact amount. Transaction ordering cannot be exploited because each transaction's outcome is deterministic and not dependent on the state of a shared pool or global price.
Attack Scenario: Unauthorized Function Access
Vulnerability: Without proper access controls, attackers might call sensitive functions to manipulate contract state or steal assets.
function unbagETH( uint256 tokenId, bytes32 messageHash, bytes memory signature, uint256 amount, address recipient, bool burnToken, bytes32 referenceId ) public nonReentrant { if (ownerOf(tokenId) != msg.sender) revert NotOwner(); bytes memory data = abi.encode(amount, recipient, burnToken, referenceId); verifySignature(tokenId, messageHash, signature, address(0), OperationType.UNBAG_ETH, data); }
Security Mechanism: Lockx implements strict access controls on all functions. Deposit functions verify the caller owns the NFT. Withdrawal functions require both ownership verification and a valid signature from the Lockx key associated with the NFT, creating a dual-authorization requirement.
Key Management
Key Fraction Technology
Lockx implements a unique key fraction technology that enhances security through a multi-party computation approach to key generation and management. This technology ensures private keys are never stored in their entirety—instead, they're deterministically derived when needed through a secure process.
Zero Trust Architecture
Our key fraction technology implements zero trust principles. Lockx never stores complete private keys—not even temporarily. Keys are derived on-demand and immediately deleted from memory after use.
How Key Fraction Technology Works
User Authentication: You sign a unique message that includes a random "message key fraction" generated for your session.
Server-Side Key Fraction: Lockx generates a random key fraction that's encrypted and stored securely in Google Cloud KMS (Key Management Service). This is protected by Hardware Security Modules (HSM) with FIPS level 3 compliance for enterprise-grade security.
Ephemeral Key Derivation: When needed, your signature is combined with the server-side key fraction to deterministically derive the public/private key pair through a cryptographic hash function. This creates a unique, one-time-use signing key that exists only for the duration of the specific operation.
Expiring Signatures: All generated signatures have a short lifespan and include operation-specific data that prevents them from being reused for other purposes. This time-bound approach provides enhanced security by limiting the window of opportunity for potential attacks.
Immediate Cleanup: After the operation is completed, the derived private key is immediately removed from memory. Keys must be rederived for every operation, ensuring no persistent key material exists that could be compromised.
Security Benefits
- No complete private key is ever stored anywhere
- Both user input (signature) and server-side fraction are required to derive the key
- Server-side key fractions are encrypted at rest
- Advanced plan users benefit from HSM protection for their key fractions
- Key rotation supported for enhanced security
Key Export & Recovery
Lockx provides you with the encrypted key fraction during setup, which you can securely store as a backup. This fraction is essential for key recovery and export:
Key Export Process
- When you need to export your private key, you'll need to provide:
- Your wallet signature
- The encrypted key fraction you received during setup
- Valid 2FA code as proof of ownership
- Once verified, Lockx temporarily reconstructs your private key for export
- The key is securely delivered to you and immediately purged from our systems
Key Ownership
Even though Lockx manages the key fraction technology, you always maintain ultimate ownership of your keys. You can export your complete key details whenever needed by proving ownership through our verification process.
2FA Protection
Lockx implements robust 2FA (Two-Factor Authentication) protection using the same trustless key derivation approach:
Trustless TOTP Management
- Lockx creates TOTP (Time-based One-Time Password) secrets using the same trustless key derivation process used for Lockx key fractions
- Like key fractions, TOTP secrets are never stored in their complete form anywhere
- The 2FA code is required to decrypt associated Lockx key fractions and export them
- Unlike traditional web2 systems, Lockx doesn't store any TOTP secrets - they are trustlessly derived on-demand
- We verify the code against your authentication application to guarantee security
Compatible Applications
Lockx 2FA is compatible with industry-standard authenticator applications:
Self custody signing
While Lockx provides a secure key fraction service, users can alternatively opt for complete Self custody of their keys. This option gives you full control and responsibility over the key management process.
Self custody vs. Lockx key fractions
Feature | Lockx key fraction | Self custody |
---|---|---|
Key storage | Encrypted key fraction in KMS | User's responsibility |
Security level | Multi-party computation with 2FA | Dependent on user's security measures |
Recovery | Supported through recovery process | User's responsibility |
Two-factor authentication | Included | Included |
Site/web app usage | Unlimited | Unlimited |
Using Self custody mode
To use Self custody mode for signing transactions, follow these steps:
- Copy the JSON provided to you during your unbagging authentication process into Remix
- Verify the parameters are correct
- Sign into Remix with your secondary signer
- Right click the file holding the JSON and click sign
- Copy the signature provided in the terminal to the frontend modal
- Click submit signature
Interactive EIP-712 message builder
DOMAIN: name: "Lockx" version: "3" chainId: 1 verifyingContract: 0x1234...5678 TYPE: Operation tokenId: uint256 nonce: uint256 opType: uint8 dataHash: bytes32 VALUE: tokenId: 123 nonce: 45 opType: 1 dataHash: [automatically generated from the parameters below] OPERATION DATA (1): signatureExpiry: 1688654321 (expires: in 15 minutes) amount: 1000000000000000000 wei recipient: 0xabcd...ef01
Important Security Notice
With Self custody, you are fully responsible for securing your private keys. Loss of your private key will result in permanent loss of access to your bagged assets. Make sure to implement proper backup procedures.
Security & Authorization
EIP-712 Signatures
Lockx uses EIP-712 signatures for secure transaction authorization. This standard provides a better user experience by showing users a structured and readable message when signing transactions.
What is EIP-712?
EIP-712 is an Ethereum Improvement Proposal that defines a standard for signing typed structured data. It improves upon simple message signing by:
- Providing human-readable data in signing interfaces
- Enabling structured data with types
- Preventing signature replay across different domains
- Ensuring consistent hashing across implementations
Implementation in Lockx
In our contracts, EIP-712 is implemented through OpenZeppelin's EIP712 contract:
bytes32 private constant OPERATION_TYPEHASH =
keccak256("Operation(uint256 tokenId,uint256 nonce,uint8 opType,bytes32 dataHash)");
constructor(address erc721Address)
EIP712("Lockx", "1")
{
_erc721 = ERC721(erc721Address);
}
When a user initiates an operation like withdraw assets, the frontend will:
- Construct the typed data according to EIP-712 specification
- Request the user to sign this data with their wallet
- Submit the signature along with the operation parameters to the contract
- The contract will verify the signature before executing the operation
const domain = {
name: "Lockx",
version: "1",
chainId: chainId,
verifyingContract: LOCKX_CONTRACT_ADDRESS
};
const types = {
Operation: [
{ name: "tokenId", type: "uint256" },
{ name: "nonce", type: "uint256" },
{ name: "opType", type: "uint8" },
{ name: "dataHash", type: "bytes32" }
]
};
Security Measures
Lockx contracts implement multiple security measures to protect user assets and ensure secure operations.
Reentrancy Protection
All functions that transfer assets implement OpenZeppelin's ReentrancyGuard to prevent reentrancy attacks.
EIP-712 Compliance
EIP-712 signatures with nonces prevent replay attacks and ensure only authorized operations.
Transfer Restrictions
Bags cannot be transferred, preventing unauthorized movement of assets.
EIP-5192 Compliance
All Lockboxes implement the EIP-5192 soulbound standard, ensuring they remain permanently locked to their owners.
Direct contract interaction
All Lockx contracts are verified on Etherscan, allowing for direct interaction with the contracts without requiring our frontend interface. This provides an additional layer of security and accessibility, ensuring your assets remain accessible even if our website becomes unavailable.
Benefits of verified contracts
- Full transparency of contract code
- Direct interaction with contract functions
- Ability to verify transaction details
- Independence from Lockx frontend
- Permanent access to your assets
Interacting with Lockx contracts on Etherscan
Step 1: Find the verified contract
Navigate to Etherscan and search for the Lockx contract address:
Alternatively, you can search by name "Lockx" in the Etherscan search bar, but be sure to verify you're interacting with the official contract.
Step 2: Navigate to the "Contract" tab
Once on the contract page, click on the "Contract" tab to see the verified contract code and interact with it.
Step 3: Use the "Read Contract" section
The "Read Contract" section lets you query contract state without spending gas:
- getFullLockbox(tokenId) - View all assets stored in your Lockbox
- locked(tokenId) - Verify if a token is soulbound (always returns true)
- ownerOf(tokenId) - Check the owner of a specific Lockbox
- getActiveLockxPublicKeyForToken(tokenId) - Get the current signing key for a bag
- getNonce(tokenId) - Get the current nonce for a bag (needed for signatures)
Note: Some functions are restricted to the token owner. If you're not connected with the owner's wallet, you'll receive an error when calling these functions.
Step 4: Use the "Write Contract" section
The "Write Contract" section allows you to modify contract state by executing transactions:
Connect your wallet
Before interacting with write functions, connect your wallet by clicking "Connect to Web3" at the top of the Write Contract section.
Common write functions
- depositETH(tokenId, referenceId) - Deposit ETH into your bag
- depositERC20(tokenId, tokenAddress, amount, referenceId) - Deposit ERC20 tokens
- depositERC721(tokenId, nftContract, nftTokenId, referenceId) - Deposit NFTs
- unbagETH(...) - Withdraw ETH (requires signature)
- unbagERC20(...) - Withdraw ERC20 tokens (requires signature)
- unbagERC721(...) - Withdraw NFTs (requires signature)
- rotateLockxKey(...) - Change the signing key (requires signature)
Important: For functions requiring signatures (unbag operations), you'll need to generate EIP-712 signatures. This typically requires using our frontend or signing utilities like eth-sig-util. The process is complex and requires precise formatting of message data.
Example: Checking your lockbox contents
Let's walk through the process of checking what's in your Lockbox:
- Navigate to the "Read Contract" section
- Find the
getFullLockbox
function - Enter your token ID in the input field
- Click the "Query" button
- The function will return three values:
- bagETH: The amount of ETH stored (in wei)
- erc20Tokens: Array of token addresses and balances
- nfts: Array of NFT contracts and token IDs
[bagETH]: 1000000000000000000 [erc20Tokens]: [ [0]: { tokenAddress: 0x6B175474E89094C44Da98b954EedeAC495271d0F, balance: 50000000000000000000 } ] [nfts]: [ [0]: { nftContract: 0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D, nftTokenId: 1234 } ]
Advanced tips for Etherscan interaction
Using the correct network
Make sure you're using Ethereum Mainnet when accessing the Lockx contract. The contract is deployed on Ethereum Mainnet only, and the verification and interaction features will only work with the correct network selected.
Reading events
Check the "Events" tab to see all emitted events from the contract, including deposits, withdrawals, and key rotations. This can be useful for tracking activity or verifying operations.
Decoding transaction input data
When viewing a transaction involving the Lockx contract, Etherscan will automatically decode the function call and parameters due to contract verification, making it easier to understand what each transaction does.
Verifying contract addresses
Always double-check contract addresses by comparing them with official sources. The verified contract will have a green checkmark and the "Contract" label next to the address on Etherscan.
FAQ & Support
Frequently Asked Questions
Lockx is a secure platform for managing digital assets (ETH, ERC20 tokens, and NFTs) through smart contract "bags" that provide enhanced security features through EIP-712 signatures.
Lockx is built to defend against many common Self custody wallet attacks:
- Wallet private key or seed phrase compromise:
If your wallet's private key or seed phrase is compromised, attackers could easily transfer or drain your funds. With Lockx, your assets are held inside a soulbound NFT, and withdrawals require a separate Lockx signature derived from an ephemeral key. Even if your main key is compromised, the Lockbox and its bagged assets remain secure. The attacker would need BOTH your compromised wallet keys AND the secondary Lockbox key. With 2FA protection, an attacker would also need access to your mobile device to recreate your secondary key. You can quickly transfer your assets from your Lockbox to a non-compromised wallet. - Signature phishing defense:
Lockx only accepts structured EIP‑712 signatures generated by your Lockx key—not your wallet's key alone. EIP-712 authenticates individual details such as token amounts, addresses, recipients, chain IDs, and expirations, ensuring operation data remains transparent and providing additional security against phished signatures. - Wallet drainers and scam sites:
Lockboxes are soulbound and cannot be drained or transferred from the wallet they are bound to. All content inside requires a separate interaction with the Lockx smart contract, which requires a separate EIP-712 typed signature. All bagged assets remain secure inside the Lockbox, allowing you to quickly transfer them to a non-compromised wallet if needed. - Malicious airdrops:
Lockboxes only accept deposits from the token owner, so the contents cannot be compromised by malicious airdrops or random tokens. - Problems with proprietary wallet infrastructure:
Unlike complex systems that rely on proprietary wallet infrastructure, Lockx assets are held inside a soulbound NFT adhering to the ERC-721 standard that any Ethereum Self custody wallet can own. The dual-key multisignature system is simple to interact with, and the smart contract is public and always accessible, ensuring no reliance on centralized infrastructure. It has no tokenomics and no dependence on off-chain signals, reducing friction even further.
Key fraction technology ensures that no complete private key is ever stored anywhere. The key is derived on-demand from a combination of your signature (which only you can produce) and an encrypted server-side key fraction. This means that an attacker would need both your wallet and access to our secure cloud infrastructure to compromise your keys. After use, the derived private key is immediately deleted from memory. Additionally, we hash resulting signatures with time-based expiry parameters to invalidate signatures after a set period, preventing long-term vulnerability. Two-factor authentication (2FA) is required to access the decrypted fractions during key recreation and the signing process, adding another critical layer of security.
With our key fraction technology, control is shared. You maintain control through your wallet's signature capability, and Lockx stores a necessary key fraction. Neither party alone can derive the private key. A valid 2FA code is also required for any key derivation process, and the 2FA system itself is built using key fraction technology, ensuring no single entity has access to complete keys. Alternatively, you can choose Self custody mode, where you manage your keys entirely without Lockx involvement.
The Lockx smart contracts are completely autonomous and operate independently on the blockchain. Even if Lockx services become unavailable, your assets remain safe and accessible. You can:
- Interact directly with the smart contracts using blockchain tools
- Generate your own EIP-712 signatures if you have your private key (either Self custody or exported)
- Use alternative frontends or tools developed by the community
This contract independence is why we offer Self custody options and always provide the ability to export your keys if using our hosted key fraction technology, which eliminates any dependency on our servers for key generation and validation. We always recommend exporting and securely backing up your keys.
No, Lockx does not have its own token or tokenomics. We operate on a platform fee model, charging one-time fees for key management services. This approach allows us to provide consistent service without token price volatility.
Lockx uses EIP-712 signatures to authorize operations. Each Lockbox has an associated public key that must sign operations like withdrawals. This provides an additional layer of security beyond just owning the NFT. Lockx key fractions are convenient because they automate key derivation and signing technology with 2FA integration. With the Lockx key fraction option, a valid 2FA code combined with a valid wallet signature will recreate the original key used to sign for operations, streamlining the entire process. Alternatively, in Self custody mode, you can sign transactions yourself by receiving the EIP-712 JSON format to sign with external signing tools like Remix.
No, Lockx bags are non-transferable by design. This is a security feature that prevents unauthorized movement of the assets contained within the bag.
If using our hosted key fraction technology, we ensure all key fractions are encrypted and stored with all relevant backups. As long as you have paid the platform fee and can verify ownership of your wallet private key, encrypted fraction, and 2FA code, you will always be able to recover your keys. If using Self custody, you are responsible for managing your own keys and we unfortunately cannot help you recover your Self custody keys.
Troubleshooting
We're here to help if you encounter any issues. Here are some common problems and their solutions:
- If you're having trouble connecting your wallet, make sure you're using the correct wallet provider and network. Try refreshing the page or using a different browser if issues persist.
- If you're unable to sign transactions, check your wallet's transaction history to see if there are any pending transactions that need to be addressed first.
- For any issues with the signature verification process, try refreshing your session and attempting again. If problems persist, please contact our support team for assistance.
- For "Injected Provider" errors, ensure that your wallet extension is properly installed and updated to the latest version.
- When interacting with dApps, make sure to grant the necessary permissions when prompted by your wallet.
- If your wallet keeps disconnecting from the dApp, try enabling the "Always connect to this site" option in your wallet settings.
- Ensure 2FA is setup and fully confirmed before accessing sensitive functions.
Contact Support
Our support team is ready to assist you with any questions or issues you may encounter.