@@ -324,7 +324,7 @@ fn validate_compiler_version(version: &str) -> Result<(), AtlasError> {
324324/// Uses an atomic write (temp → rename) so concurrent requests for the same
325325/// version don't corrupt the cached binary.
326326async fn get_solc_binary ( version : & str , cache_dir : & str ) -> Result < PathBuf , AtlasError > {
327- let target = solc_binary_target ( OS , ARCH ) ?;
327+ let target = solc_binary_target ( OS , ARCH , version ) ?;
328328 let filename = format ! ( "solc-{target}-{version}" ) ;
329329 let cache_path = PathBuf :: from ( cache_dir) . join ( & filename) ;
330330
@@ -396,16 +396,48 @@ async fn get_solc_binary(version: &str, cache_dir: &str) -> Result<PathBuf, Atla
396396 Ok ( cache_path)
397397}
398398
399- fn solc_binary_target ( os : & str , arch : & str ) -> Result < & ' static str , AtlasError > {
399+ fn solc_version_triplet ( version : & str ) -> Option < ( u64 , u64 , u64 ) > {
400+ let version = version. strip_prefix ( 'v' ) ?;
401+ let version = version. split_once ( "+commit." ) ?. 0 ;
402+ let mut parts = version. split ( '.' ) ;
403+
404+ let major = parts. next ( ) ?. parse ( ) . ok ( ) ?;
405+ let minor = parts. next ( ) ?. parse ( ) . ok ( ) ?;
406+ let patch = parts. next ( ) ?. parse ( ) . ok ( ) ?;
407+
408+ if parts. next ( ) . is_some ( ) {
409+ return None ;
410+ }
411+
412+ Some ( ( major, minor, patch) )
413+ }
414+
415+ fn solc_binary_target ( os : & str , arch : & str , version : & str ) -> Result < & ' static str , AtlasError > {
400416 match ( os, arch) {
401417 ( "linux" , "x86_64" ) => Ok ( "linux-amd64" ) ,
418+ ( "linux" , "aarch64" ) => {
419+ let Some ( version_triplet) = solc_version_triplet ( version) else {
420+ return Err ( AtlasError :: Verification ( format ! (
421+ "failed to determine native solc target for compiler version {version}"
422+ ) ) ) ;
423+ } ;
424+
425+ if version_triplet >= ( 0 , 8 , 31 ) {
426+ Ok ( "linux-arm64" )
427+ } else {
428+ Err ( AtlasError :: Verification ( format ! (
429+ "compiler version {version} is not available for linux-arm64; \
430+ official Solidity linux-arm64 binaries start at v0.8.31"
431+ ) ) )
432+ }
433+ }
402434 // Solidity's official static macOS binaries are currently published under
403435 // macosx-amd64. Apple Silicon can execute them natively via Rosetta.
404436 ( "macos" , "x86_64" ) | ( "macos" , "aarch64" ) => Ok ( "macosx-amd64" ) ,
405437 _ => Err ( AtlasError :: Verification ( format ! (
406438 "unsupported platform for native solc download: {os}/{arch}. \
407- Official Solidity static binaries are currently available for linux/x86_64 \
408- and macOS. For Docker on Apple Silicon, run atlas-server as linux/amd64 ."
439+ Official Solidity static binaries are currently available for \
440+ linux/x86_64, linux/aarch64, and macOS ."
409441 ) ) ) ,
410442 }
411443}
@@ -1004,23 +1036,34 @@ mod tests {
10041036 #[ test]
10051037 fn solc_binary_target_supports_linux_amd64 ( ) {
10061038 assert_eq ! (
1007- solc_binary_target( "linux" , "x86_64" ) . unwrap( ) ,
1039+ solc_binary_target( "linux" , "x86_64" , "v0.8.20+commit.a1b79de6" ) . unwrap( ) ,
10081040 "linux-amd64"
10091041 ) ;
10101042 }
10111043
1044+ #[ test]
1045+ fn solc_binary_target_supports_linux_arm64 ( ) {
1046+ assert_eq ! (
1047+ solc_binary_target( "linux" , "aarch64" , "v0.8.31+commit.2d38a763" ) . unwrap( ) ,
1048+ "linux-arm64"
1049+ ) ;
1050+ }
1051+
10121052 #[ test]
10131053 fn solc_binary_target_supports_macos_arm64_via_rosetta ( ) {
10141054 assert_eq ! (
1015- solc_binary_target( "macos" , "aarch64" ) . unwrap( ) ,
1055+ solc_binary_target( "macos" , "aarch64" , "v0.8.20+commit.a1b79de6" ) . unwrap( ) ,
10161056 "macosx-amd64"
10171057 ) ;
10181058 }
10191059
10201060 #[ test]
1021- fn solc_binary_target_rejects_linux_arm64 ( ) {
1022- let err = solc_binary_target ( "linux" , "aarch64" ) . unwrap_err ( ) ;
1023- assert ! ( matches!( err, AtlasError :: Verification ( _) ) ) ;
1061+ fn solc_binary_target_rejects_old_linux_arm64_versions ( ) {
1062+ let err = solc_binary_target ( "linux" , "aarch64" , "v0.8.30+commit.73712a01" ) . unwrap_err ( ) ;
1063+
1064+ assert ! (
1065+ matches!( err, AtlasError :: Verification ( message) if message. contains( "not available for linux-arm64" ) )
1066+ ) ;
10241067 }
10251068
10261069 #[ test]
0 commit comments