검증된 계약, 프록시, 그리고 아무도 말하지 않는 업그레이드 키

·7분 읽기·작성자: SSP Editorial Team
SSP Academy 표지: 검증된 스마트 계약, 프록시, 업그레이드 키

검증된 계약, 프록시, 그리고 아무도 말하지 않는 업그레이드 키

블록 탐색기에는 계약 소스 코드 검증됨이라고 적힌 초록색 체크 표시가 있고, 엄청나게 많은 사람이 그것을 "이 계약은 안전하다"로 읽습니다.

그런 뜻이 아닙니다. 훨씬 좁고 훨씬 쓸모 있는 무언가를 뜻하며, 그 둘을 혼동하는 것이야말로 신중한 사람들이 끝내 결코 동의하지 않았을 것들을 승인하게 되는 경로입니다.

"검증됨"이 실제로 증명하는 것

계약은 바이트코드로 배포됩니다 — 기계 명령이고, 실무적으로는 읽을 수 없습니다. 검증이란 원래의 소스 코드를 올려서, 명시된 컴파일러 판본과 설정으로 그것을 컴파일하면 그 주소에 이미 살고 있는 바이트코드가 정확히 나온다는 사실을 탐색기가 확인해 주도록 하는 일입니다.

주장의 전부는 이것입니다. 당신이 읽고 있는 소스가 정말로 돌아가고 있는 소스다.

이는 실재하고 값어치 있는 보장입니다. 이것이 없다면, 어떤 프로젝트의 GitHub에 올라온 말끔해 보이는 코드가 당신의 거래가 곧 건드릴 그것과 조금이라도 관계가 있는지 알 길이 없습니다.

그러나 그것이 말하지 않는 모든 것에 주목하십시오. 검증은 감사가 아닙니다. 그 코드가 옳은지, 결함이 있는지, 함수 이름이 암시하는 것과 비슷한 무엇이라도 하는지 아무도 평가하지 않았습니다. claimRewards라는 이름의 함수가 당신 잔액 전부를 배포자에게 옮기는 계약도 검증될 수 있고, 그 검증은 전적으로 정직할 것입니다 — 그 절도가 바로 코드가 하겠다고 말한 그것임을 참되게 증명해 줄 테니까요.

검증됨은 읽을 수 있다는 뜻이지, 믿을 만하다는 뜻이 아닙니다. 물음을 "이게 무엇인가?"에서 "내가 방금 읽은 것을 이해했는가?"로 옮겨 줍니다. 그것은 진전이지만, 두 번째 물음에 당신 대신 답해 주지는 않습니다.

그 반대도 중요합니다. 검증되지 않은 계약이 악의의 증거는 아닙니다 — 정당한 배포 가운데 많은 수가 끝내 검증까지 가지 못합니다. 하지만 그것은 아무도 — 당신이 쓰는 어떤 도구도, 당신에게 경고했을 법한 어떤 연구자도 — 당신이 곧 상호작용할 것을 읽을 수 없다는 뜻입니다. 그 점을 조심하는 것은 합당합니다.

그리고 프록시가 일을 더 어렵게 만든다

여기서 발밑이 흔들리고, 대개 언급되지 않고 지나가는 부분이 이것입니다.

당신이 상호작용할, 간단치 않은 계약 대부분은 단일 계약이 아닙니다. 그것들은 프록시입니다. 프록시는 당신이 보는 주소이고, 잔액과 허용량과 상태 등 모든 자료를 쥐고 있습니다. 그러나 논리는 거의 담고 있지 않습니다. 대신 모든 호출을 별도의 구현 계약으로 넘기고, 그 계약이 말하는 대로 그저 실행할 뿐입니다.

까닭은 업그레이드 가능성입니다. 불변 계약은 기울 수 없으니 결함은 영구적이고 빠진 기능은 영영 빠진 채입니다. 프록시를 새 구현으로 가리키게 하면, 모든 이용자에게 옮겨 오라고 요청하지 않고도 팀이 결함을 고치고 개선을 내보낼 수 있습니다. 고칠 수 없는 결함으로 얼마나 많은 값어치가 사라졌는지를 생각하면, 이는 방어할 수 있는 공학적 선택입니다.

여기에 놓치기 쉬운 귀결이 있습니다. 탐색기에서 프록시를 찾아 검증됨이라고 볼 때, 당신이 검증한 것은 전달 논리이지 행동이 아닙니다. 당신의 돈에 무슨 일이 벌어질지를 실제로 결정하는 코드는 구현 주소에 살고 있고, 탐색기가 그것을 눈에 띄게 보여 줄 수도 아닐 수도 있으며, 그것은 교체될 수 있습니다.

그러니 진짜 물음은 애초에 "이 계약은 검증되었는가?"가 아니었습니다. 이것입니다.

누가 이 계약의 행동을 바꿀 수 있으며, 얼마나 빨리 바꿀 수 있는가?

관리자 키가 실제 보안 모형이다

업그레이드 가능한 모든 계약에는 그 업그레이드를 수행할 수 있는 누군가가 있습니다. 지금 코드가 얼마나 훌륭하든, 그 권한이 곧 보안 모형입니다.

폭은 섬뜩한 것에서 합당한 것까지 이릅니다.

외부 소유 계정 하나. 누군가의 기계에 있는 개인 키 하나가 당신 자금을 쥔 계약의 논리를 갈아 끼울 수 있습니다. 그것이 피싱당하거나 도난당하거나 주인이 강요당하면, 계약은 공격자가 원하는 무엇이든 됩니다. 이 구성은 마땅한 정도보다 흔합니다.

다중 서명. 여러 서명자가 동의해야 합니다. 훨씬 낫습니다 — 단일 실패 지점을 없앱니다 — 다만 서명자가 몇인지, 그리고 그들이 정말로 독립된 사람들인지 아니면 같은 팀의 노트북 네 대인지는 알아 둘 값어치가 있습니다.

시간 잠금 뒤의 다중 서명. 업그레이드는 체인에 공지되고, 고정된 지연 — 흔히 24시간에서 72시간 — 이 지나야만 실행될 수 있습니다. 의미 있는 것이 이것입니다. 당신의 처지를 통째로 바꾸기 때문입니다. 변경을 미리 통보받고, 효력이 생기기 전에 빠져나올 창을 얻습니다. 시간 잠금이 악의적 업그레이드를 막지는 않습니다. 그것을 살아남을 수 있는 것으로 만듭니다.

업그레이드 경로가 아예 없음. 계약은 불변입니다. 예측 가능성은 최대, 결함이 발견되었을 때 손쓸 방도는 영. 정당한 선택이고, 보통 그것에 걸 만큼 오래 실전에서 단련된 프로토콜이 택합니다.

이 가운데 무엇도 저절로 옳지는 않습니다. 그러나 "키 하나"와 "다중 서명에 이틀의 지연"의 차이는, 아무도 실수하지 않기를 바라는 것과 누군가 실수했을 때 반응할 시간이 있는 것의 차이입니다.

왜 이것이 하필 승인을 물어뜯는가

이 대목은 당신이 실제로 자주 하는 일과 이어집니다.

토큰 승인을 내줄 때, 당신은 어떤 주소에 당신의 토큰을 옮길 권한을 줍니다. 코드 한 조각이 아니라 주소에요. 그 승인은 토큰 계약의 저장 공간에 앉아 무기한 남습니다.

그 주소가 업그레이드 가능한 프록시라면, 당신의 토큰을 옮길 자격을 지닌 논리는 당신이 승인한 뒤에, 당신의 개입도 당신의 새 서명도 없이 교체될 수 있습니다. 당신이 살펴본 것은 하나이고, 계속 노출되는 것은 다른 하나입니다.

그래서 더 이상 쓰지 않는 승인을 취소하라는 상시의 조언이 처음 보이는 것보다 무겁습니다. 어떤 계약에 결함이 드러나느냐의 문제만이 아닙니다. 업그레이드 가능한 계약에 준 무제한 허용량은, 당신이 그것을 열어 두는 내내, 업그레이드 키를 쥔 그 누구에게든 내준 허가라는 것입니다.

이는 거래 시뮬레이션의 가장 날카로운 한계이기도 합니다. 서명 전에 시뮬레이션하기는 거래가 현재 상태와 현재 구현에 대해 무엇을 하는지 알려 줍니다. 정말 쓸모 있고, 같은 승인이 다음 달에 무엇을 허용할지는 알려 줄 수 없습니다.

SSP가 보여 주는 것, 그리고 멈추는 지점

SSP Key가 승인을 제시할 때는 날 16진수를 보여 주는 대신 호출 데이터를 해독합니다. 표준 ERC-20 선택자 — approve, transfer, transferFrom, increaseAllowance, setApprovalForAll — 를 알아보고 평이한 말로 옮기며, 무제한 허용량도 표시합니다. 코드에서는 2^255 이상의 모든 금액이 그렇게 정의되어 있습니다.

해독기는 일부러 조심스럽습니다. 그 자신의 머리말이 그것을 오직 표현 계층이라고 서술합니다. 서명되는 내용을 결코 바꾸지 않고, 닫히는 쪽으로 실패합니다. 알 수 없는 선택자, 잘못된 길이, 뭉개진 16진수, 표준이 아닌 주소 채움 — 모두 아무것도 돌려주지 않고 "고급" 보기 뒤에 날 16진수를 둔 일반 동작으로 물러나게 만듭니다. 자신만만하게 짐작하고 틀리느니 모른다고 인정하는 쪽을 택합니다. 토큰의 기호와 소수 자릿수는 기기 안 등록부에서 확실히 알 때만 붙이고, 결코 추정하지 않습니다.

이제 정직한 경계입니다. 해독기에는 프록시라는 개념이 없습니다. 구현 계약이라는 관념이 그 안 어디에도 없습니다. "당신은 0xABC…에 무제한 USDC 허용량을 주고 있습니다"라고 정확하고 분명하게 말해 줄 수 있습니다 — 그리고 0xABC가 프록시라는 것, 그 업그레이드 키를 누가 쥐고 있는지, 다음 주에는 그 행동이 아주 달라질 수 있다는 것은 말해 줄 수 없습니다.

이는 실수라기보다 어떤 지갑 해독기도 넘을 수 없는 경계입니다. 해독은 눈앞의 호출을 서술합니다. 상대방이 업그레이드 가능한지, 누가 그것을 다스리는지는 더 넓은 세계의 성질이고 따로 확인해야 합니다. 우리는 자신 있어 보이는 승인 화면이 갖추지 못한 완전함을 넌지시 풍기게 두느니, 그 경계를 말로 밝히는 쪽을 택합니다.

의미 있는 무언가를 승인하기 전의 실질적인 점검

검증되었는가? 아니라면, 당신이 기대는 것은 평판뿐임을 이해하십시오.

프록시인가? 탐색기가 이를 표시합니다 — 프록시 안내나 "Read as Proxy" 항목을 찾으십시오. 있다면, 중요한 코드는 구현 쪽입니다.

누가 업그레이드할 수 있고, 지연이 있는가? 목록에서 가장 값어치 있는 물음이자 거의 아무도 묻지 않는 물음입니다. 이것을 고민한 프로젝트는 문서로 남깁니다. 고민하지 않았거나 말하지 않으려는 프로젝트는, 그것으로 이미 당신에게 무언가를 말한 셈입니다.

승인이 무제한이어야 하는가? 대개 아닙니다. 실제로 쓸 작정인 금액을 승인하면, 그 계약이 나중에 무엇이 되든 당신의 노출은 딱 거기까지로 묶입니다.

끝났으면 취소하십시오. 열린 허용량은 상설 허가이고, 당신의 주의보다 오래 삽니다.

할 값어치가 있는 마음의 조정은 작지만 많은 것을 바꿉니다. 검증은 지금 이 순간 어떤 코드가 돌고 있는지를 말해 줍니다. 업그레이드 가능성은 내일 무엇이 돌지를 누가 정하는지를 말해 줍니다. 위험의 거의 전부는 두 번째 물음에 살고, 제공되는 안심의 거의 전부는 첫 번째에만 답합니다.

이 글 공유하기

관련 글