
셀프서비스 계정 생성
VP-0002
요약
본 제안은 네트워크 거버넌스가 소유하는 new.vaulta 계정을 생성하고, 계정 생성 컨트랙트를 그 계정에 배포합니다. 이를 통해 지갑, 거래소, 안내 문서는 개별 운영자의 키가 아니라 네트워크 합의로 보증되는 하나의 표준 계정 생성 창구를 갖게 됩니다. 이 컨트랙트는 셀프서비스, 결제 기반입니다. 사용자가 네트워크 토큰으로 비용을 지불하면, 컨트랙트가 운영자 개입 없이 단일 단계로 계정을 생성하고 해당 계정의 RAM을 구매합니다. 시행은 두 번의 BP MSIG(15/21) 단계로 이루어집니다. 계정을 생성한 뒤, 게시된 해시의 컨트랙트 코드를 배포합니다.
근거
계정 생성의 표준 창구는 네트워크가 하나 소유해야 합니다. 계정은 체인을 사용하기 위한 최소 전제이며, 지갑이나 거래소, 안내 문서가 신규 사용자에게 new.vaulta를 안내한다면, 그것은 어떤 운영자의 선의가 아니라 15/21 BP 합의로 동작이 보증되는 컨트랙트를 가리키는 것입니다.
기능 자체는 이미 검증되었습니다. 같은 컨트랙트가 2025년 10월부터 create.gm에서 실제로 운영되며 Vaulta 메인넷에 계정을 생성해 왔습니다. 빠져 있는 것은 네트워크의 소유권입니다. create.gm은 개별 키로 통제됩니다. 그 키를 가진 사람은 예고 없이 언제든 배포된 코드를 교체할 수 있으므로, 컨트랙트를 감사한 통합 업체라 하더라도 자기 사용자의 결제를 받는 코드가 무엇인지 보장받지 못합니다. 운영자 한 명이 서비스를 중단하거나 키를 잃으면 체인의 정문이 함께 사라집니다. 또한 인터페이스가 메모를 담은 토큰 전송뿐이므로, 진짜 생성 컨트랙트와 결제만 받고 아무것도 돌려주지 않도록 만들어진 모조품을 가르는 것은 신뢰받는 이름 하나뿐입니다. new.vaulta 아래에서는 코드가 실행 전에 공개적으로 보이는 msig를 통해서만 변경되고, 계정은 네트워크가 존속하는 한 함께 존속하며, 네트워크가 하나의 창구를 진짜라고 지명한 것이 됩니다.
메커니즘
계정 및 권한
new.vaulta는 다른*.vaulta계정들과 동일한 패턴을 따라 BP MSIG(15/21)을 통해 생성됩니다. 두 권한 모두 생성 시의eosio::newaccount액션에서 설정되므로 이후updateauth는 뒤따르지 않습니다.owner와active는 모두eosio.prods@active에 위임되며, 이는 15/21 BP 합의로 귀결됩니다.active는 추가로new.vaulta@eosio.code를 포함하므로 컨트랙트가 자체 권한으로 인라인 액션을 전송할 수 있습니다. 해당 액션은eosio::newaccount,core.vaulta::buyram, 초과 결제분을 돌려주는core.vaulta::transfer, 그리고 자체logcreation입니다.- 따라서 향후 모든
setcode/setabi에도 동일한 15/21 승인이 필요합니다. 더 낮은 임계값의 관리 권한은 존재하지 않으며, 컨트랙트에는 그런 권한을 필요로 하는 관리자 액션 자체가 없습니다. - 모든 컨트랙트 매개변수(결제 토큰, 바이트 제공량, 프록시 컨트랙트)는 컴파일 타임 상수입니다. 이 중 무엇이든 변경하는 것은 곧 코드 변경입니다. 새로 게시된 커밋과 해시가 15/21
setcode로 승인되어야 하며, 설정 액션은 존재하지 않습니다.
컨트랙트 인터페이스
이 컨트랙트는 직접 호출되는 액션이 아니라 토큰 전송 알림으로 구동됩니다.
| 액션 | 권한 | 목적 |
|---|---|---|
transfer 알림(*::transfer) |
토큰 송신자 | core.vaulta가 발행한 결제 토큰을 수신하면 메모를 파싱하고, 계정을 생성하며, RAM을 구매하고, 초과분을 환급 |
parsememo(memo)(읽기 전용) |
없음 | accountname-PUBLICKEY를 계정명과 단일 키 권한으로 파싱 |
estimatecost()(읽기 전용) |
없음 | 계정 생성 1건의 현재 토큰 비용을 반환 |
logcreation(account, from, excess, ram, timestamp) |
new.vaulta |
인덱싱을 위해 생성마다 발생시키는 인라인 로그 액션. from은 결제 전송을 보낸 계정으로, 생성되는 계정과 반드시 일치하지는 않습니다 |
메모 형식은 accountname-PUBLICKEY입니다(PUB_ 및 레거시 키 형식 모두 허용). 각 생성은 3,260바이트의 RAM 비용에 시스템 수수료를 더한 금액을 지출하며, 사용자는 최소 그만큼을 전송해야 합니다. 초과분은 신규 계정으로 이전됩니다. 계정이 실제로 받는 RAM은 그 결제 금액이 시장 가격으로 구매하는 양이므로 3,260바이트에 정확히 맞아떨어지지 않고 그 부근에 놓이며, 여기에 네트워크의 기본 계정당 할당량이 더해집니다.
결제는 core.vaulta가 발행한 지정 토큰(A, 소수점 4자리)으로만 받습니다. 컨트랙트는 자신이 수신자가 아닌 전송, 자신이 보내는 전송, 그리고 eosio.ram이나 core.vaulta가 보낸 전송을 거부하지 않고 통과시키며, 여기에는 컨트랙트 자신의 RAM 구매와 buyram 과정에서 결제 토큰을 언래핑하며 core.vaulta가 컨트랙트로 되돌려 보내는 구간이 포함됩니다. 메모가 bypass인 경우를 제외하면 다른 토큰의 전송은 거부되며 전송 트랜잭션이 실패합니다.
메모 bypass를 담은 전송은 계정을 생성하지 않고 그대로 수락되어 보관됩니다. 이것이 컨트랙트에 직접 자금을 넣는 방법입니다. 메모를 토큰보다 먼저 확인하므로, 어떤 토큰 컨트랙트의 어떤 토큰이든 bypass 전송이면 보관됩니다. 컨트랙트에는 그 자금을 밖으로 옮기는 액션이 없으므로, 이렇게 보낸 잔액은 15/21 setcode가 경로를 마련할 때까지 그대로 남습니다.
요청한 계정명이 이미 존재하면 전송은 실패하고 결제자는 토큰을 그대로 보유합니다.
자금 및 운영 비용
- 일회성:
new.vaulta계정 자체와 배포된 코드를 위한 RAM은 신규 컨트랙트 계정에 대한 일반적인 관행에 따라, 생성 MSIG의 일부로 네트워크가 부담합니다. 생성 단계에서eosio를 지불자로 하여 409,600바이트를 구매하며, 이는 배포가 청구하는 약 390,000바이트에 여유를 두어 산정한 값입니다. 컨트랙트는 테이블을 저장하지 않으므로 사용량은 코드와 ABI뿐입니다. - 지속 비용: 운영은 전적으로 사용자가 부담합니다. 각 생성의 CPU와 NET은 트랜잭션의 첫 서명자인 결제 사용자에게 청구되며, 생성된 계정의 RAM은 사용자의 결제 금액으로 트랜잭션 안에서 구매됩니다. 생성이 끝나도 컨트랙트 자신의 토큰 잔액은 그대로이며 RAM 사용량도 늘지 않습니다. 환급된 초과분의 잔액 행은
core.vaulta가 부담하기 때문입니다.new.vaulta는 스테이킹이 필요 없으며, 보유하는 잔액은bypass메모를 통해 들어온 것뿐입니다.
제한
컨트랙트는 속도나 규모 제한을 두지 않으며, 이는 의도된 것입니다.
- 보조금이 없습니다. 사용자는 RAM 비용 전액과 시스템 수수료를 지불하며, 스팸 발송자가 소진시킬 기금이나 쿼터 풀이 존재하지 않습니다.
- 계정 생성은 비용을 지불할 의사가 있는 누구에게나 이미 프로토콜 수준에서 무허가로 열려 있습니다.
new.vaulta를 통한 대량 유료 계정 생성은 원시newaccount+buyram으로 하는 것과 정확히 같은 정도로 가능하고, 정확히 같은 비용이 듭니다. 컨트랙트가 더하는 것은 편의뿐입니다. - 규모는 본질적으로 고정되어 있습니다. 모든 생성은 3,260바이트에 해당하는 비용을 지출하고, 전송 1건당 계정 1개이며, 초과 결제분은 신규 계정으로 환급됩니다.
- 이름 규칙은 변하지 않습니다. 생성 주체로서
new.vaulta는 일반 이름만 만들 수 있습니다. 요청하는 이름은 점 없이a-z와1-5만 사용한 정확히 12자여야 합니다. 12자 미만의 점 없는 이름은 낙찰된 이름 경매를 요구하고, 점이 있는 이름은 접미사 소유자의 권한을 요구하는데,new.vaulta는 둘 중 어느 것도 갖지 못하기 때문입니다.
사용 패턴
사용자는 단일 토큰 전송으로 계정을 생성합니다.
estimatecost(읽기 전용)를 호출해 현재 가격을 확인합니다. 견적과 전송 사이에 RAM 가격이 움직일 수 있으므로, 견적에 약간의 여유분을 더해 보내는 것이 관례입니다. 견적과 정확히 같은 금액은 경계에서 실패할 수 있으며, 여유분은 신규 계정으로 환급되어 그 계정의 초기 잔액이 됩니다.- 메모
myaccount123-PUB_K1_...와 함께 그 이상의 네트워크 토큰을new.vaulta로 전송합니다. 이때 이름은 제한 절의 규칙을 충족해야 합니다. - 컨트랙트가 주어진 키를 단일
owner/active권한으로 하여myaccount123을 생성하고,core.vaulta를 통해myaccount123의 RAM을 구매하며, 초과 지불분을myaccount123에게 환급합니다.
생성된 계정은 RAM은 보유하지만 CPU와 NET이 없으므로, 환급받은 잔액을 옮기거나 updateauth를 실행하는 일을 스스로 할 수 없습니다. 지갑이 해당 계정의 첫 트랜잭션을 공동 서명하거나 파워업해 주는 것이 전제입니다.
하나의 키가 두 권한을 모두 담당하는 것은 의도된 설계입니다. 별도의 owner 키, 멀티시그, 계정 기반 복구와 같은 구성은 생성 이후 updateauth로 설정합니다.
범위 경계
- 본 제안은
new.vaulta계정과 그 계정 생성 컨트랙트만을 다룹니다. - 수익 메커니즘 없음: 컨트랙트는 RAM 비용에 시스템 수수료만을 부과하며, 초과분은 생성된 계정으로 환급합니다.
미해결 질문
없음.
다음 단계
컨트랙트 소스는 contracts/create에 공개되어 있습니다.
배포 단계가 제안하는 산출물은 다음과 같습니다.
- 커밋:
d103fdcea03bf2a6e3e0ff5ed893ec10389c29a2 - 코드 해시:
7166a16ea0d6db98fe18cde9a2d56b30f091dcbb19efcd0a0b5fa0e510f272c8, 38,534바이트 WASM에 대한 값 - ABI 해시:
4f47d205f7cc990efb548d002f324e9c23c8a5ab65012dbab4430973e3c7ffdb, 610바이트 직렬화 ABI에 대한 값 - CDT: v4.1.1, 툴체인 컨테이너의 빌드 인자로 고정
재현하려면 해당 커밋을 체크아웃하고 make build/create/production을 실행하며, 컴파일은 그 컨테이너 안에서 이루어집니다. shasum -a 256 contracts/create/build/create.wasm이 코드 해시를 내주고, contracts/create/build/create.abi를 바이너리로 직렬화하면 610바이트가 되며 그 해시가 ABI 해시입니다. 두 값은 create.gm이 Vaulta 메인넷에서 실행 중인 값과 같으며, get_raw_abi가 code_hash와 abi_hash로 반환합니다.
- 저자는 배포 단계를 제안하기 전에 코드 해시, 빌드 기준 커밋, 이를 재현하는 CDT 버전을 이 섹션에 기록하여 BP가 직접 빌드해 비교할 수 있게 함
- 저자는 본 제안의 최종 텍스트를 담은 커밋에 고정한 백레퍼런스 인용을 각 단계의 트랜잭션에 추가함