Skip to content

Commit

Permalink
feat: BaseSource now does source validation using EIP-712
Browse files Browse the repository at this point in the history
  • Loading branch information
donosonaumczuk committed Dec 29, 2024
1 parent 4a80b96 commit f69ec12
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 14 deletions.
43 changes: 34 additions & 9 deletions contracts/core/base/BaseSource.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ import {ISource} from "./../interfaces/ISource.sol";
import {SourceStamp} from "./../types/Types.sol";

abstract contract BaseSource is ISource {
uint256 internal immutable EC_SIGNATURE_LENGTH = 65;
bytes2 internal immutable EIP191_VERSION_BYTE_0X00_HEADER = 0x1900;
bytes2 internal immutable EIP191_VERSION_BYTE_0X01_HEADER = 0x1901;
string constant EIP712_DOMAIN_VERSION = "1";
bytes32 constant EIP712_DOMAIN_VERSION_HASH = keccak256(bytes(EIP712_DOMAIN_VERSION));
bytes32 constant EIP712_DOMAIN_TYPEHASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
bytes32 constant SOURCE_STAMP_TYPEHASH = keccak256("SourceStamp(address source,uint256 nonce,uint256 deadline)");

mapping(uint256 => bool) internal _wasSourceStampNonceUsed;

Expand All @@ -24,13 +28,8 @@ abstract contract BaseSource is ISource {
require(!_wasSourceStampNonceUsed[sourceStamp.nonce]);
require(sourceStamp.deadline >= block.timestamp);
require(sourceStamp.source == address(this));
require(sourceStamp.signature.length == EC_SIGNATURE_LENGTH);
_wasSourceStampNonceUsed[sourceStamp.nonce] = true;
bytes32 sourceStampHash = keccak256(
abi.encodePacked(
EIP191_VERSION_BYTE_0X00_HEADER, sourceStamp.source, sourceStamp.nonce, sourceStamp.deadline
)
);
bytes32 digest = _calculateDigest(_calculateHashStruct(sourceStamp));
bytes32 r;
bytes32 s;
uint8 v;
Expand All @@ -40,11 +39,37 @@ abstract contract BaseSource is ISource {
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
address signer = ecrecover(sourceStampHash, v, r, s);
address signer = ecrecover(digest, v, r, s);
require(_isValidSourceStampSigner(signer));
}

function _isValidSourceStampSigner(
address signer
) internal virtual returns (bool);

function _calculateHashStruct(
SourceStamp memory sourceStamp
) private pure returns (bytes32) {
return keccak256(abi.encode(SOURCE_STAMP_TYPEHASH, sourceStamp.source, sourceStamp.nonce, sourceStamp.deadline));
}

function _calculateDigest(
bytes32 hashStruct
) private view returns (bytes32) {
return keccak256(
abi.encodePacked(EIP191_VERSION_BYTE_0X01_HEADER, _calculateDomainSeparatorHashStruct(), hashStruct)
);
}

function _calculateDomainSeparatorHashStruct() private view returns (bytes32) {
return keccak256(
abi.encode(
EIP712_DOMAIN_TYPEHASH,
keccak256("Lens Source"),
EIP712_DOMAIN_VERSION_HASH,
block.chainid,
address(this)
)
);
}
}
18 changes: 13 additions & 5 deletions contracts/rules/base/RestrictedSignersRule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,15 @@ abstract contract RestrictedSignersRule is MetadataBased {
"RestrictedSignerMessage(bytes4 functionSelector,bytes abiEncodedParams,uint256 nonce,uint256 deadline)"
);

constructor(string memory metadataURI) {
constructor(
string memory metadataURI
) {
_setMetadataURI(metadataURI);
}

function _emitMetadataURISet(string memory metadataURI) internal override {
function _emitMetadataURISet(
string memory metadataURI
) internal override {
emit Lens_Rule_MetadataURISet(metadataURI);
}

Expand Down Expand Up @@ -125,7 +129,9 @@ abstract contract RestrictedSignersRule is MetadataBased {
_validateRecoveredAddress(digest, signature);
}

function _calculateMessageHashStruct(RestrictedSignerMessage memory message) private pure returns (bytes32) {
function _calculateMessageHashStruct(
RestrictedSignerMessage memory message
) private pure returns (bytes32) {
return keccak256(
abi.encode(
RESTRICTED_SIGNER_MESSAGE_TYPEHASH,
Expand All @@ -137,7 +143,9 @@ abstract contract RestrictedSignersRule is MetadataBased {
);
}

function _calculateDigest(bytes32 messageHashStruct) private view returns (bytes32) {
function _calculateDigest(
bytes32 messageHashStruct
) private view returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", _calculateDomainSeparatorHashStruct(), messageHashStruct));
}

Expand All @@ -148,7 +156,7 @@ abstract contract RestrictedSignersRule is MetadataBased {
keccak256("Lens Protocol Restricted Signer Rule"),
EIP712_DOMAIN_VERSION_HASH,
block.chainid,
msg.sender // This is the address of the primitive, and we assume the primitive calls the rule
msg.sender // TODO: This is using primitive's address, maybe should be address(this), so it's rule addr
)
);
}
Expand Down

0 comments on commit f69ec12

Please sign in to comment.