Releases: ethereum/sourcify
v2.2.4
- Update chain 7001 test
- Accept update-chain-xxx branch name for chain tests
- Add Promtail config to push nginx logs to Loki
What's Changed
- update-chain-7001 -- New RPC endpoints and test contracts for ZetaChain Athens3 Testnet by @CharlieMc0 in #1051
- Nginx grafana by @kuzdogan in #1060
- Quick Release by @kuzdogan in #1061
Full Changelog: v2.2.3...v2.2.4
v2.2.3
- New Chains
- Bitkub (96)
- Cronos (25)
- Elysium Mainnet (1339)
- Taiko Alpha v3 (167005)
- Update Symplexia (1149) test contracts
- Fix lerna bootsrap failing in CI
- Add cronoscan in Etherscan tests
- Fix Moonbeam scan test
What's Changed
- Add chain 25925 (Bitkub Chain Testnet) by @ppanya in #1046
- Add chain 96 (Bitkub Chain) by @ppanya in #1047
- Add Cronos Chain 25 by @crmax-it in #1049
- Add Elysium Mainnet chain by @aqeelVaival in #1055
- Update_Chain_1149 by @symplexialabs in #1057
- Release by @kuzdogan in #1058
New Contributors
- @ppanya made their first contribution in #1046
- @crmax-it made their first contribution in #1049
- @aqeelVaival made their first contribution in #1055
Full Changelog: v2.2.2...v2.2.3
v2.2.2
Release v2.2.1
What's Changed
- Fix Matomo configs after migration
- Fixes for chain verification tests
- New chains:
- Dogechain (2000)
- Symplexia Smart Chain (1149)
- Turned off support for chains:
- POA Sokol (77)
- Boba Rinkeby (28)
- Candle (534)
- Darwinia Pangolin (43)
- Gather Devnet (486217935)
- Crystaleum (103090)
- POA Core (99)
- Astar (592)
- Gnosis Chiado (10200)
- Flare (14)
- Optimism Bedrock Alpha (28528)
Note that on the prev PR named Release v2.2.1, the commit tag was not generated and no release was actually done.
Pull requests
- Throw before if compiled bytecode empty instead of later in creation bytecode by @kuzdogan in #1022
- Add Symplexia Smart Chain (1149) by @symplexialabs in #1007
- Fix for chain verification tests by @kuzdogan in #1031
- add-chain-2000 (dogechain) by @oliviachef in #1039
New Contributors
- @symplexialabs made their first contribution in #1007
- @oliviachef made their first contribution in #1039
Full Changelog: v2.2.0...v2.2.1
Release 2.2.0
What's Changed
Features
- Verification with Standard JSON Input
- Added support for new chains (295, 7668, 7672, 888, 999, and 7701)
- Implemented a complete Metadata type
- Generate variations of the metadata file in partial match to reach a full match
- Added "Lookup Another" button in Lookup result
- Add server monitoring capabilities to Grafana
- Added GitHub star button
Fixes
- Etherscan metadata variations
- Fix EventManager fails if listeners are not set
- Update h5ai-nginx submodule to the latest version
- Fix how the UI handles non-checksummed addresses
- Reorder the metadata object before generating the variations
- Add test for not alphabetically sorted metadata
- Disable chainId 51 getCreatorTx test
- Re-enable SourcifyEventManager's listeners
- Add a repository link to the create2 verified contracts
- Use checkSupportedChainId instead of checkChainId for contract verification
- Update typescript and typedoc in lib-sourcify
- Handle libraries with call protection
- Add nginx exporter for Prometheus
- Improve the function to sanitize path at storeSources
- Display the create2 repo link only for create2 results
- Fix abitype req. typescript v5+
- Show error on bad Etherscan req
- Change OPTIMISTIC_ETHERSCAN to OPTIMISMSCAN
- Revert accidentally setting sed to gsed
- Fix matchWithCreationTx by decoding the constructor arguments
- Test for paths in metadata containing multiple ../
- Fix linter errors and warnings
Fixed vulnerabilities
Thanks to @Hellobloc for reporting the following vulnerabilities.
Path traversal vulnerability when storing contracts
Summary
When the file path is saved with ../ as prefix, the file is potentially saved in other locations in the repository.
Example
Solution
The solidity compiler collapses all the /../
components in the path, the same algorithm was implemented in Sourcify to fix the path traversal vulnerability.
Malicous creation bytecode bypass the startsWith check in matchWithCreationTx
Summary
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.
Example
https://github.com/Hellobloc/verify/tree/test_start_with
https://repo.staging.sourcify.dev/contracts/partial_match/5/0x5ea1E75790b86C4c5Db5e7c7A1fa14d683D50Cfe/sources/contracts/
Solution
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.
PRs
- Etherscan metadata variations by @kuzdogan in #976
- Fix how the ui handles non-checksummed addresses by @marcocastignoli in #990
- add-chain-999 by @lolieatapple in #993
- Add chain 888 by @lolieatapple in #995
- Verification with Standard JSON Input by @kuzdogan in #980
- Add chain 7668 by @aidan-starke in #1004
- Add chain 7672 by @aidan-starke in #988
- Implement a complete Metadata type by @marcocastignoli in #1001
- Re-enable SourcifyEventManager's listeners by @marcocastignoli in #1003
- Add chain 7701 by @tster in #1005
- Handle libraries with call protection by @marcocastignoli in #1000
- Add chain 295 (Hedera Mainnet) by @svienot in #1009
- Release by @marcocastignoli in #1016
New Contributors
- @lolieatapple made their first contribution in #993
- @aidan-starke made their first contribution in #1004
- @tster made their first contribution in #1005
- @svienot made their first contribution in #1009
Full Changelog: v2.1.1...v2.2.0
Release 2.1.1
What's Changed
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.
Fixed vulnerability
Summary
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.
Example
- Given a partial match on Sourcify (you can use Import from Etherscan for
0x345a7c9325E7145CA7E8aafabf474361E6c674D5
on Goerli) - Download this repo: https://github.com/Hellobloc/verify
- Edit the file
final2.sol
as follows
pragma solidity ^0.5.10;
contract Deployer {
constructor() public {
bytes memory bytecode = hex'6080604052348015600f57600080fd5b506004361060285760003560e01c8063d1524f7414602d575b600080fd5b60336075565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff168156fea265627a7a72315820b59b9ccfbe01c3596a27c9bf3fc5728c39c25d61c263777e6e6a96dbb69a677a64736f6c63430005110032';
assembly {
return (add(bytecode, 0x20), mload(bytecode))
}
}
}
- Generate the keccak256 of that file and update the keccak256 field of
final2.sol
in the metadata.json - Use Sourcify's API to verify the contract
Explanation
The 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 bytecode
Solution
We've considered several solutions:
- If during
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.- We don’t solve the issue because a malicious code could force the length to be the same.
- Checking the equivalence of the metadata hash after a perfect match.
- This case makes use of this fact: the malicious file that generated a "perfect bytecode" needs a fake metadata (recall we modified the
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. - However this method is not resolved for partial matches.
- **Remove
matchWithSimulation**
The vulnerability comes from this functionality. We were already considering removing this verification as with the recent addition ofimmutableRefences
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: v2.1.0...v2.1.1
v2.1.0
What's Changed
- Added basic test coverage
- Fix: Handling Etherscan contracts with multiple sources
- Use the respective solc binary according to the platform, save binaries locally
- Update Etherscan chains
- Users can now import contracts from other Etherscan instances: Polygonscan, Snowtrace etc.
- Make use of
immutableReferences
on verification- This lets us verify contracts with immutables very often without needing alternative methods such as looking at the
creatorTxHash
or "simulation"
- This lets us verify contracts with immutables very often without needing alternative methods such as looking at the
- Fix
addLibraryAddresses
potential vulnerability with regex.
Fixed vulnerability
Thanks to @Hellobloc and @samczsun for reporting the vulnerability.
addLibraryAddress RegExp vulnerability
Risk Description
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.
Example
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.
DOS Attack
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.
Solution
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).
PRs
- Added wagmi to tools in the landing page by @SaTiSH-K-R in #962
- handle etherscan contracts with multiple sources by @marcocastignoli in #965
- Test coverage by @marcocastignoli in #963
- Default SolcJs compiler by @marcocastignoli in #964
- Add other Etherscan chains by @kuzdogan in #959
- Verify with
immutableReferences
by @kuzdogan in #973 - Fix CORS error on req too large by @kuzdogan in #977
- Handle solc links in repo when fetching compiler by @marcocastignoli in #979
- fix: auto-scroll to about section by @aalimsahin in #982
- Change how addLibraryAddresses replaces the library addresses from the recompiled bytecode by @marcocastignoli in #981
- Release by @kuzdogan in #985
New Contributors
- @SaTiSH-K-R made their first contribution in #962
- @aalimsahin made their first contribution in #982
Full Changelog: v2.0.0...v2.1.0
v2.0.0
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.
- Codebase refactoring with
lib-sourcify
library:- Removes the old npm packages
@ethereum-sourcify/core
-verification
and-validation
. - Maintain the main verification functionality in a reusable package
@ethereum-sourcify/lib-sourcify
, including types etc.
- Removes the old npm packages
- Fix Etherscan regex for the new Etherscan
- Fix created contract address calculation with the nonce
- Add monitoring support to Meter Network
- Use local IPFS gateway in tests instead of ipfs.io/ipfs
- Add
creatorTxHash
parameter to verification API - New Chains:
- Bear Network Chain Mainnet #641230
- Base Goerli Testnet #938
What's Changed
- Add chain 641230 by @kuzdogan in #934
lib-sourcify
refactoring (w/ rebase) by @kuzdogan in #935- Add chain 84531 by @kuzdogan in #938
- update: explorer endpoint by @jessepinkman9900 in #939
- Use a local ipfs gw on tests by @kuzdogan in #946
- User input creator tx by @kuzdogan in #942
- File not saved after CREATE2 verification by @marcocastignoli in #957
- Release v2 by @kuzdogan in #960
Full Changelog: v1.2.2...v2.0.0
v1.2.2
What's Changed
- Update chains.json
- Stringify compiler errors
- Persist compiler binaries
- New Chains:
Full Changelog: v1.2.1...v1.2.2
v1.2.1
- update Chainsafe S3
- fix dockerfile for IPFS
- added ens to featured contracts
- Update Avalanche subnet creation data address
- New chains:
- Flare (14)
- Stratos Testnet (2047)
- Songbird Canary Network (19)
New Contributors
- @yash251 made their first contribution in #899
- @Uttam-Singhh made their first contribution in #907
- @jasonatran made their first contribution in #901
- @BoThe1K made their first contribution in #912
Full Changelog: v1.2.0...v1.2.1