Last active
August 17, 2023 13:54
-
-
Save ssadler/ff3b3456b8d55e1a2ae1497143f990df to your computer and use it in GitHub Desktop.
Solidity code for cryptographic provenance verification
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// See blog post: https://ssadler.substack.com/p/contract-provenance-verification-175 | |
interface IProvenance { | |
function getProvenanceData() external returns (uint salt, bytes32 codeHash); | |
} | |
contract Provenance is IProvenance { | |
bytes32 immutable _salt; | |
bytes32 immutable _codeHash; | |
constructor(bytes32 salt) { | |
_salt = salt; | |
_codeHash = _deployGetCodeHash(); | |
} | |
function _deployGetCodeHash() internal pure returns (bytes32 codeHash) { | |
// The code hash that is used in the create2 address preimage is the hash of | |
// all of the creation code, which we can access using codecopy. | |
assembly { | |
let code := mload(0x40) | |
// don't need to update mem position, we're not using it again? | |
//mstore(0x40, add(code, add(0x20, mul(0x20, div(codesize(), 0x20))))) | |
codecopy(code, 0, codesize()) | |
codeHash := keccak256(code, codesize()) | |
} | |
} | |
function getProvenanceData() override external view returns (uint salt, bytes32 codeHash) { | |
return (uint(_salt), _codeHash); | |
} | |
} | |
/* | |
* In order to verify legitimate proxy as cheaply as possible, and in a (relatively) | |
* non revokable way, it is done cryptographically; each proxy has hardcoded it's | |
* salt and creation code hash, so together with the address of the minting contract, | |
* the address can be recreated and verified. | |
*/ | |
function verifyProvenanceWithSalt(address creator, IProvenance target) view returns (bool ok, uint salt) { | |
/// @solidity memory-safe-assembly | |
assembly { | |
let ptr := mload(0x40) | |
mstore(ptr, creator) | |
mstore(0, hex"2f00ef5c") // cast sig "getProvenanceData()" | |
pop(staticcall(1000, target, 0, 4, add(ptr, 0x20), 64)) | |
salt := mload(add(ptr, 0x20)) | |
let start := add(ptr, 0x0b) | |
mstore8(start, 0xff) | |
let computed := keccak256(start, 85) | |
computed := and(computed, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) | |
ok := eq(computed, target) | |
} | |
} | |
function verifyProvenance(address creator, IProvenance target) view returns (bool) { | |
(bool ok,) = verifyProvenanceWithSalt(creator, target); | |
return ok; | |
} |
sukri03
commented
Aug 17, 2023
__
``
- [ ]
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment