계정 등록
이전 튜토리얼에서 토큰의 초기 순환 공급을 발행하는 방법과 이벤트 표준에 따라 이벤트를 기록하는 방법을 살펴보았습니다. 그런 다음 컨트랙트를 배포하고 지갑 잔고에서 FT를 확인했습니다. 이 튜토리얼에서는 스토리지 관리 표준에 대해 알아보고, FT 컨트랙트에 계정을 등록하여 악의적인 사람이 컨트랙트에서 모든 자금을 고갈시키는 것을 방지하는 방법에 대해 알아봅니다.
소개
새로운 사람이 대체 가능한 토큰(FT)을 받을 때마다 컨트랙트의 accounts
조회 맵에 추가됩니다. 이렇게 하면 컨트랙트에 바이트가 추가됩니다. 모든 사용자가 무료로 FT를 받을 수 있도록 만들면, 해당 시스템이 쉽게 악용될 수 있습니다. 사용자는 기본적으로 소량의 FT를 많은 계정에 전송하여, 모든 컨트랙트의 자금을 "탈취"할 수 있습니다. 이러한 이유로, 사용자가 저장하는 정보와 컨트랙트에 사용하는 바이트에 대해 요금을 청구할 수 있습니다. 그러나 사용자에게 청구하는 이 방법은 모든 컨트랙트에서 작동하도록 표준화되어야 합니다.
스토리지 관리 표준 입력
스토리지 관리 표준
스토리지 관리 표준은 컨트랙트에서 스토리지에 대해 사용자에게 요금을 청구하는 방식을 제어하는 일련의 규칙입니다. 표준을 구현하는 모든 컨트랙트가 서로 상호 운용될 수 있도록 하는 함수와 동작을 설명합니다. 구현해야 하는 3가지 함수는 다음과 같습니다.
storage_deposit
- 사용자가 일정량의 스토리지를 컨트랙트에 예치할 수 있습니다. 사용자가 초과된 금액을 예지하면, 초과한 $NEAR는 환불됩니다.storage_balance_of
- 주어진 사용자가 지불한 스토리지를 쿼리합니다.storage_balance_bounds
- 주어진 컨트랙트와 상호 작용하는 데 필요한 최소 및 최대 스토리지 양을 쿼리합니다.
이러한 함수 개요를 통해, 흐름이 다음과 같다고 가정할 수 있습니다.
- 사용자가 컨트랙트에 존재하지 않는 경우, 사용하는 바이트를 충당하기 위해 일부 스토리지를 예치해야 합니다.
- 사용자가
storage_deposit
함수를 통해 $NEAR를 입금하면, 컨트랙트와 자유롭게 상호 작용할 수 있습니다.
보증금이 얼마인지 스스로에게 물어볼 수 있습니다. 이 정보를 얻는 방법에는 두 가지가 있습니다.
- 모든 개별 사용자가
storage_deposit
함수에서 차지하는 바이트를 맵에 삽입하고, 바이트를 측정한 다음, 나중에accounts
맵에서 제거하여 동적으로 계산합니다. - 컨트랙트를 초기화할 때, 가능한 한 가장 큰 계정 ID를 삽입하기 위한 바이트를 계산하고, 모든 사용자에게 동일한 금액을 청구합니다.
단순화를 위해 두 번째 방법을 가정하겠습니다.
컨트랙트 수정
이 "가장 긴 계정 ID의 바이트"는 storage_deposit
함수 실행 중에 값을 가져오고, 사용자가 충분한 $NEAR를 첨부할 수 있도록 컨트랙트 상태에 저장되어야 합니다. src/lib.rs
파일을 열고 Contract
구조체에 다음 코드를 추가합니다. 지금 가입하는 경우 3.initial-supply
폴더에서 이 튜토리얼의 뼈대 코드를 찾을 수 있습니다.
loading...
You'll now need a way to calculate this amount which will be done in the initialization function. Move to the src/internal.rs
file and add the following private function measure_bytes_for_longest_account_id
which will add the longest possible account ID and remove it while measuring how many bytes the operation took. It will then set the bytes_for_longest_account_id
field to the result.
loading...
또한 스토리지 비용을 지불한 후 계정을 "등록"하는 함수를 만들고 싶을 것입니다. 이렇게 하려면 잔고가 0인 상태로 accounts
맵에 삽입하기만 하면 됩니다. 이렇게 하면 현재 맵에 있는 모든 계정이 "등록"된 것으로 간주되고, 스토리지 비용을 지불했음을 알 수 있습니다. FT를 받으려는 계정은 잔고가 0 이상인 상태로 맵에 있어야 합니다. 그렇지 않은 경우 컨트랙트 실행이 취소됩니다.
loading...
사용자가 아직 존재하지 않는 경우, 사용자 정의 메시지로 패닉하는 함수도 만들어 봅시다.
loading...
이제 internal_deposit
함수를 호출할 때, 사용자 잔액이 아직 존재하지 않는 경우 다음을 통해 기본값 0
으로 설정하는 대신:
let balance = self.accounts.get(&account_id).unwrap_or(0);
You can replace it with the following:
loading...