Skip to content

Commit

Permalink
Simple witness allocator
Browse files Browse the repository at this point in the history
  • Loading branch information
vimageDE committed Jan 10, 2025
1 parent cbe6b3a commit 8e38af9
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
76 changes: 76 additions & 0 deletions src/examples/allocator/SimpleWitnessAllocator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.27;

import { ERC6909 } from "lib/solady/src/tokens/ERC6909.sol";
import { IERC1271 } from "openzeppelin-contracts/contracts/interfaces/IERC1271.sol";
import { IAllocator } from "src/interfaces/IAllocator.sol";
import { ITheCompact } from "src/interfaces/ITheCompact.sol";
import { SimpleAllocator } from "src/examples/allocator/SimpleAllocator.sol";
import { ISimpleWitnessAllocator } from "src/interfaces/ISimpleWitnessAllocator.sol";
import { Compact } from "src/types/EIP712Types.sol";
import { ResetPeriod } from "src/lib/IdLib.sol";

contract SimpleWitnessAllocator is SimpleAllocator, ISimpleWitnessAllocator {
// abi.decode(bytes("Compact(address arbiter,address "), (bytes32))
bytes32 constant COMPACT_TYPESTRING_FRAGMENT_ONE = 0x436f6d70616374286164647265737320617262697465722c6164647265737320;
// abi.decode(bytes("sponsor,uint256 nonce,uint256 ex"), (bytes32))
bytes32 constant COMPACT_TYPESTRING_FRAGMENT_TWO = 0x73706f6e736f722c75696e74323536206e6f6e63652c75696e74323536206578;
// abi.decode(bytes("pires,uint256 id,uint256 amount)"), (bytes32))
bytes32 constant COMPACT_TYPESTRING_FRAGMENT_THREE = 0x70697265732c75696e743235362069642c75696e7432353620616d6f756e7429;
// uint200(abi.decode(bytes(",Witness witness)Witness("), (bytes25)))
uint200 constant WITNESS_TYPESTRING = 0x2C5769746E657373207769746E657373295769746E65737328;

constructor(address compactContract_, address arbiter_, uint256 minWithdrawalDelay_, uint256 maxWithdrawalDelay_)
SimpleAllocator(compactContract_, arbiter_, minWithdrawalDelay_, maxWithdrawalDelay_) {}

/// @inheritdoc ISimpleWitnessAllocator
function lockWithWitness(Compact calldata compact_, bytes32 typestringHash_, bytes32 witnessHash_) external {
bytes32 tokenHash = _checkAllocation(compact_);

bytes32 digest = keccak256(
abi.encodePacked(
bytes2(0x1901),
ITheCompact(COMPACT_CONTRACT).DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
typestringHash_, // keccak256("Compact(address arbiter,address sponsor,uint256 nonce,uint256 expires,uint256 id,uint256 amount,Witness witness)Witness(uint256 witnessArgument)")
compact_.arbiter,
compact_.sponsor,
compact_.nonce,
compact_.expires,
compact_.id,
compact_.amount,
witnessHash_
)
)
)
);

_claim[tokenHash] = compact_.expires;
_amount[tokenHash] = compact_.amount;
_nonce[tokenHash] = compact_.nonce;
_sponsor[digest] = tokenHash;

emit Locked(compact_.sponsor, compact_.id, compact_.amount, compact_.expires);
}

/// @inheritdoc ISimpleWitnessAllocator
function getTypestringHashForWitness(string calldata witness_) external pure returns (bytes32 typestringHash_) {
assembly ("memory-safe") {
let memoryOffset := mload(0x40)
mstore(memoryOffset, COMPACT_TYPESTRING_FRAGMENT_ONE)
mstore(add(memoryOffset, 0x20), COMPACT_TYPESTRING_FRAGMENT_TWO)
mstore(add(memoryOffset, 0x40), COMPACT_TYPESTRING_FRAGMENT_THREE)
mstore(add(memoryOffset, sub(0x60, 0x01)), shl(56, WITNESS_TYPESTRING))
let witnessPointer := add(memoryOffset, add(sub(0x60, 0x01), 0x19))
calldatacopy(witnessPointer, witness_.offset, witness_.length)
let witnessEnd := add(witnessPointer, witness_.length)
mstore8(witnessEnd, 0x29)
typestringHash_ := keccak256(memoryOffset, sub(add(witnessEnd, 0x01), memoryOffset))

mstore(0x40, add(or(witnessEnd, 0x1f), 0x20))
}
return typestringHash_;
}
}
29 changes: 29 additions & 0 deletions src/interfaces/ISimpleWitnessAllocator.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.27;

import { ISimpleAllocator } from "src/interfaces/ISimpleAllocator.sol";
import { Compact } from "src/types/EIP712Types.sol";

interface ISimpleWitnessAllocator is ISimpleAllocator {

/// @notice Locks the tokens of an id for a claim with a witness
/// @dev Locks all tokens of a sponsor for an id with a witness
/// @dev example for the typeHash:
/// keccak256("Compact(address arbiter,address sponsor,uint256 nonce,uint256 expires,uint256 id,uint256 amount,Witness witness)Witness(uint256 witnessArgument)")
///
/// @param compact_ The compact that contains the data about the lock
/// @param typeHash_ The type hash of the full compact, including the witness
/// @param witnessHash_ The witness hash of the witness
function lockWithWitness(Compact calldata compact_, bytes32 typeHash_,bytes32 witnessHash_) external;

/// @notice Returns the witness typestring hash including a given witness argument
/// @dev example of a witness type string input:
/// "uint256 witnessArgument"
/// @dev full typestring:
/// Compact(address arbiter,address sponsor,uint256 nonce,uint256 expires,uint256 id,uint256 amount,Witness witness)Witness(uint256 witnessArgument)
///
/// @param witness_ The witness typestring argument
/// @return typestringHash_ The full compact typestring hash, including the witness
function getTypestringHashForWitness(string calldata witness_) external pure returns (bytes32 typestringHash_);
}

0 comments on commit 8e38af9

Please sign in to comment.