ERC-7945 기밀 전송 지원 토큰 (Confidential Transactions Supported Token)

Final · 토큰 · 2025-05-09 작성

계정 잔액과 전송 금액을 암호화된 데이터로 숨기는 토큰의 공통 인터페이스입니다. 지갑과 앱이 구현 방식에 얽매이지 않고 금액을 드러내지 않는 토큰을 다룰 수 있게 합니다.

왜 필요한가

이더리움의 표준 토큰(ERC-20)은 모든 계정의 잔액과 전송 금액이 블록체인에 그대로 공개됩니다. 누구나 특정 주소가 얼마를 갖고 얼마를 보냈는지 볼 수 있어 금액에 민감한 개인이나 기관은 쓰기 어렵습니다. 모네로나 지캐시처럼 프로토콜 차원에서 금액을 숨기는 블록체인도 있고 Zether처럼 프로토콜을 바꾸지 않고 스마트 컨트랙트로 구현한 기법도 있지만 이더리움에는 이런 기밀 토큰을 위한 공통 표준이 거의 없었습니다. 그래서 사용자와 앱은 어떤 토큰 컨트랙트가 기밀 전송을 지원하는지 쉽게 알아볼 수 없고 실제 금액을 드러내지 않고 안정적으로 전송할 수도 없었습니다. 이 표준은 잔액 조회, 전송, 위임 전송, 승인과 관련 이벤트라는 최소한의 공통 표면만 정해 서로 다른 증명 방식과 암호문 인코딩, 규제 대응 절차가 하나의 인터페이스 뒤에서 공존할 수 있게 합니다.

구현해야 하는 것

심층 설명

모든 금액은 bytes 타입의 암호화 데이터입니다

이 표준에서 잔액, 전송 금액, 허용량은 모두 bytes 타입으로 주고받습니다. confidentialBalanceOf(address owner)는 uint256 숫자가 아니라 bytes memory 형태의 암호화된 잔액을 돌려줍니다. 표준은 이 bytes를 어떻게 암호화하고 직렬화할지, 어떤 증명 시스템을 쓸지 정하지 않으며 구현이 자유롭게 정합니다. 원문은 예시로 Zether 방식 구현을 들며 이 경우 잔액과 전송 금액이 ElGamal 공개키로 동형 암호화됩니다. 이렇게 최소한의 인터페이스만 정한 덕분에 서로 다른 증명 시스템, 암호문 인코딩, 규제 대응 워크플로가 하나의 공통 인터페이스 뒤에서 공존할 수 있습니다.

confidentialTransfer와 증명 검증

confidentialTransfer(_to, _confidentialTransferValue, _proof)는 암호화된 값 뒤에 숨겨진 value만큼의 토큰을 _to에게 보내며 반드시(MUST) ConfidentialTransfer 이벤트를 발생시켜야 합니다. 호출자의 _proof 검증에 실패하면 revert해야 합니다(SHOULD). Zether식 구현 예시에서 _proof는 세 가지를 검증합니다. 전송 금액이 호출자와 _to 양쪽의 공개키로 올바르게 암호화되었는지, 숨겨진 value가 음수가 아닌지, 호출자의 기밀 잔액이 그 value를 지불하기에 충분한지입니다.

위임 전송 confidentialTransferFrom

confidentialTransferFrom(_from, _to, _confidentialTransferValue, _proof)는 _from의 토큰을 _to에게 대신 보내는 함수로, 컨트랙트가 사용자를 대신해 토큰을 옮기거나 하위 통화로 수수료를 걷는 출금형 워크플로에 쓰입니다. _from 계정이 어떤 방식으로든 호출자를 의도적으로 승인하지 않았다면 revert해야 하고(SHOULD), 증명 검증에 실패해도 revert해야 합니다(SHOULD). Zether식 예시에서 증명은 금액이 _from, _to, 호출자 세 공개키로 암호화되었는지, 금액이 비음수인지, 호출자의 기밀 허용량이 충분한지를 검증합니다.

ERC-20 approve와 크게 다른 confidentialApprove

confidentialApprove를 부르면 호출자의 기밀 잔액이 허용분(allowance part)과 나머지(left part)로 쪼개지고 두 부분 뒤의 값을 합치면 원래 잔액 뒤의 값과 같다는 등식이 성립합니다. _spender는 허용분이 0이 될 때까지 confidentialTransferFrom을 여러 번 불러 꺼내 쓸 수 있고 부를 때마다 허용분 뒤의 값이 전송 금액만큼 줄어듭니다. 나머지는 호출자의 새 기밀 잔액이 됩니다. 함수를 다시 부르면 기존 허용분을 먼저 호출자의 기밀 잔액에 합친 뒤, 새 _confidentialValue로 허용분을 덮어씁니다. 남은 허용분은 confidentialAllowance(_owner, _spender)로 조회합니다.

이벤트 발생 규칙

ConfidentialTransfer 이벤트는 토큰이 전송될 때 반드시(MUST) 발생해야 합니다. confidentialTransferFrom으로 전송되면 _spender를 호출자 주소로 설정해야 하고(MUST), 그 외에는 0x0으로 설정해야 합니다(SHOULD). 토큰을 새로 발행(mint)할 때는 _from을 0x0으로, 소각(burn)할 때는 _to를 0x0으로 설정한 ConfidentialTransfer를 발생시켜야 합니다(SHOULD). ConfidentialApproval 이벤트는 confidentialApprove(address,bytes,bytes) 호출이 성공할 때마다 반드시(MUST) 발생해야 합니다.

confidentialTotalSupply를 필수로 두지 않은 이유

ERC-20의 totalSupply() 같은 필드는 기밀성과 충돌합니다. 모든 사용자가 총발행량을 조회하고 복호화할 수 있다면, 발행이나 소각 전후의 값을 비교해 실제로 발행되거나 소각된 금액을 알아낼 수 있어 기밀성이 사라지기 때문입니다. 그래서 이 표준은 confidentialTotalSupply()를 필수로 두지 않고 자금세탁방지와 감사가 필요한지 평가해 구현이 선택적으로 지원하도록 했습니다. 소수의 당사자 그룹만 암호문 뒤의 평문 총발행량을 알 수 있게 하면 훨씬 현실적으로 운영할 수 있습니다.

감사와 자금세탁방지 지원

은행이나 금융기관처럼 정부·통화당국의 감독을 받는 발행자를 위해 confidentialTransfer의 함수 시그니처를 바꾸지 않고 파라미터에 더 많은 정보를 인코딩하는 방식으로 감사를 지원할 수 있습니다. 원문이 드는 Zether류 구현 예시에서는 호출자가 전송 금액을 호출자, 받는 사람, 그리고 감사인 그룹의 공개키로 중복 암호화해 관련 당사자들만 실제 금액을 정확히 알 수 있게 합니다. confidentialTotalSupply()에도 같은 방식을 쓸 수 있습니다.

ERC-20 겸용 팻 토큰과 선택적 메타데이터

기밀 토큰은 ERC-20을 동시에 구현할 수도 있습니다. 이런 팻 토큰(Fat Token)의 계정은 평문 잔액과 기밀 잔액 두 가지를 보유할 수 있고 ERC-20 평문 잔액을 기밀 잔액으로 숨기거나 반대로 기밀 잔액을 평문 잔액으로 되돌리는 메서드를 선택적으로 제공할 수 있습니다. 원문은 ERC-20 인터페이스가 기밀 토큰에 훨씬 큰 사용성과 효용을 가져다준다고 설명합니다. 한편 name, symbol, decimals를 담은 IERC7945Metadata 인터페이스는 선택 사항(OPTIONAL)이어서 다른 인터페이스나 컨트랙트는 이 값이 있다고 기대해서는 안 됩니다(MUST NOT).

쓸 때 주의할 점

ERC 원문 · ← ERCs