Decentralized Solidity contract source code verification service
MIT License
Bot releases are visible (Hide)
Published by kuzdogan over 1 year ago
Note that on the prev PR named Release v2.2.1, the commit tag was not generated and no release was actually done.
Full Changelog: https://github.com/ethereum/sourcify/compare/v2.2.0...v2.2.1
Published by marcocastignoli over 1 year ago
Thanks to @Hellobloc for reporting the following vulnerabilities.
When the file path is saved with ../ as prefix, the file is potentially saved in other locations in the repository.
The solidity compiler collapses all the /../
components in the path, the same algorithm was implemented in Sourcify to fix the path traversal vulnerability.
The start_with vulnerability enables arbitrary source code verification.
When comparing Creation Code, bytecode comparison is performed using the start_with function. This is designed to facilitate source code validation when constructor arguments are present.
However, relying solely on start_with for source code validation without verifying constructor arguments can introduce risks.
In particular, it is possible to create contract source code without compilation results by utilizing abstract and interface contracts. Such source code can pass the start_with check for any contract bytecode.
https://github.com/Hellobloc/verify/tree/test_start_with
https://repo.staging.sourcify.dev/contracts/partial_match/5/0x5ea1E75790b86C4c5Db5e7c7A1fa14d683D50Cfe/sources/contracts/
This problem is solved by decoding the rest of the bytecode after startsWith
assuming it is the ABI encoded constructor arguments part. If the decoding fails, an error is thrown.
Full Changelog: https://github.com/ethereum/sourcify/compare/v2.1.1...v2.2.0
Published by marcocastignoli over 1 year ago
Removed verification through simulation because of the potential vulnerability to "hijack" a contract verification by embedding the deployed bytecode inside the constructor in assembly.
Thanks to @Hellobloc and @samczsun for reporting the following vulnerabilities.
Given a partial or unverified contract, it is possible to "fully verify" any contract by just returning the deployed (onchain) bytecode of the contract inside the constructor in assembly. The verified source file would then not contain the original source file but just a few lines of code with the raw deployed bytecode.
0x345a7c9325E7145CA7E8aafabf474361E6c674D5
on Goerli)final2.sol
as followspragma solidity ^0.5.10;
contract Deployer {
constructor() public {
bytes memory bytecode = hex'6080604052348015600f57600080fd5b506004361060285760003560e01c8063d1524f7414602d575b600080fd5b60336075565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fea265627a7a72315820b59b9ccfbe01c3596a27c9bf3fc5728c39c25d61c263777e6e6a96dbb69a677a64736f6c63430005110032';
assembly {
return (add(bytecode, 0x20), mload(bytecode))
}
}
}
final2.sol
in the metadata.jsonThe function verifyDeployed tries to verify the contract with different methods, in order:
matchWithDeployedBytecode
: compare the deployed runtime bytecode with the recompiled runtime bytecodematchWithSimulation
: execute the recompiled creation bytecode on an EVM (hence "simulation"), which will produce a runtime bytecode and compare it with the deployed onematchWithCreationTx
When using Sourcify's API to verify the ´Hellobloc/verify´ contract:
matchWithDeployedBytecode
fails because recompiled runtime bytecode and the onchain runtime bytecode differ:recompiled runtime bytecode:
0x6080604052600080fdfea265627a7a72315820ff612b856b9428c30f2fecfa6f13c7a7ee8d459a3c22f6c8a900e7a0459aba5f64736f6c63430005110032
onchain runtime bytecode:
0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063d1524f7414602d575b600080fd5b60336075565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fea265627a7a72315820b59b9ccfbe01c3596a27c9bf3fc5728c39c25d61c263777e6e6a96dbb69a677a64736f6c63430005110032
matchWithSimulation
succeed because it actually produces the same runtime bytecode as the deployed runtime bytecodeWe've considered several solutions:
matchWithDeployedBytecode
we find that the length of the “trimmed” part of runtime bytecode differs then we are probably sure that the contract is neither a partial or a perfect match.
keccak256
above). Till now we assumed that if the compiler generated a "perfect runtime bytecode" then it was also true that the provided metadata was the correct one, but that's not the case. In this case, because assembly code is utilized, the "simulation" returns a "perfect runtime bytecode" but in fact the metadata hash of the metadata JSON, output from the recompilation is different than what's in the onchain CBOR encoded part.matchWithSimulation**
immutableRefences
to verification, we wouldn't need alternative verifications for contracts with immutables.We decided to comment out matchWithSimulation
type verification and eventually remove it from the codebase.
Full Changelog: https://github.com/ethereum/sourcify/compare/v2.1.0...v2.1.1
Published by kuzdogan over 1 year ago
immutableReferences
on verification
creatorTxHash
or "simulation"addLibraryAddresses
potential vulnerability with regex.Thanks to @Hellobloc and @samczsun for reporting the vulnerability.
Previously the following code was used to replace libraryAddress
es.
export function addLibraryAddresses(
template: string,
real: string
): {
replaced: string;
libraryMap: StringMap;
} {
const PLACEHOLDER_START = '__$';
const PLACEHOLDER_LENGTH = 40;
const libraryMap: StringMap = {};
let index = template.indexOf(PLACEHOLDER_START);
for (; index !== -1; index = template.indexOf(PLACEHOLDER_START)) {
const placeholder = template.slice(index, index + PLACEHOLDER_LENGTH);
const address = real.slice(index, index + PLACEHOLDER_LENGTH);
libraryMap[placeholder] = address;
const regexCompatiblePlaceholder = placeholder
.replace('__$', '__\\\\$')
.replace('$__', '\\\\$__');
const regex = RegExp(regexCompatiblePlaceholder, 'g');
template = template.replace(regex, address);
}
return {
replaced: template,
libraryMap,
};
}
The code replaced the library placeholders in the bytecode by identifying __$
and constructed regular matching expressions from the placeholder.
But note that not all versions use the hash of the library name as a placeholder. For example, the 0.4
Solidity version uses __{Path:FileName}__
placeholder.
This allows a malicious user to manipulate regular expressions, which in turn allows other parts of the bytecode to be marked as a library address.
As with the risks mentioned above, we can achieve arbitrary regular expression tampering by changing the file name of the library contract.
An example is the following:
pragma solidity ^0.4.0;
import "./$.{37}|2{40}|cantbematchedcharacters__";
contract A {
address constant public a = address(0x2222222222222222222222222222222222222222);
uint public b;
function cc() public{
b = L_.get4();
}
}
In the above code, a regular expression is written in the filename and the expression appears in the generated bytecode and is adopted by the addLibraryAddresses
function.
This regular expression will first replace itself, and then look for 22...22
to do the same. Here 2{40}
can also be modified to 5b.{...}
to perform arbitrary replacements of executable bytecode.
A real attack case(0x4AD29c9716569f3c466BB123Efdd0B9B43207dE1 in goerli) was constructed.
The tampering of constants in the above case is possible. Of course executable bytecode tampering is also possible, simply by changing
2{40}
to 5b.{...}
, and writing L_
address to the bytecode we want.
In addition to performing bytecode tampering, one can also perform a DOS attack on Sourcify. Specifically, once can design a regular expression that will not have any matches in bytecode
, resulting in __$
not being replaced, which in turn makes addLibraryAddresses
a dead loop.
We replaced the regex replacement of the pattern with a simple string match to __
in the bytecode, and replacing the placeholder with a fixed length (40 chars = 20 bytes).
immutableReferences
by @kuzdogan in https://github.com/ethereum/sourcify/pull/973
Full Changelog: https://github.com/ethereum/sourcify/compare/v2.0.0...v2.1.0
Published by kuzdogan over 1 year ago
This is the release for the v2 of Sourcify. It is a MAJOR release because of the significant changes to the codebase. The server API does not have breaking changes but has additions.
lib-sourcify
library:
@ethereum-sourcify/core
-verification
and -validation
.@ethereum-sourcify/lib-sourcify
, including types etc.creatorTxHash
parameter to verification APIlib-sourcify
refactoring (w/ rebase) by @kuzdogan in https://github.com/ethereum/sourcify/pull/935
Full Changelog: https://github.com/ethereum/sourcify/compare/v1.2.2...v2.0.0
Published by kuzdogan over 1 year ago
Full Changelog: https://github.com/ethereum/sourcify/compare/v1.2.1...v1.2.2
Published by marcocastignoli over 1 year ago
New Contributors
Full Changelog: https://github.com/ethereum/sourcify/compare/v1.2.0...v1.2.1
Published by kuzdogan almost 2 years ago
sourcify-chains
EventManager
and log events onto console and to a Grafana dashboardcontextVariables
i.e. msgSenger
and abiEncodedConstructorArguments
. This enables verifying contracts created by a factory contract and that contain immutables.contractFetchAddress
https://github.com/ethereum/sourcify/pull/889/commits/3069c98a4c8577a6839161565d15826da9127b60
Full Changelog: https://github.com/ethereum/sourcify/compare/v1.1.0...v1.2.0
Published by marcocastignoli almost 2 years ago
Published by marcocastignoli almost 2 years ago
The release includes:
Published by marcocastignoli about 2 years ago
Initial release for Sourcify.
Sourcify is a Solidity source code and metadata verification tool and repository and acts as a base layer allowing other tools build on top of it. We aim to keep as much as smart contract metadata and verified source code open and available via IPFS, and facilitate an improved smart contract UX with verified sources and decoded transactions.
The release includes: