본문으로 건너뛰기

팩토리

팩토리는 자체적으로 컴파일된 컨트랙트를 저장하고 하위 계정(sub-account)에 배포하는 것을 자동화하는 스마트 컨트랙트입니다.

다음과 같은 두 가지의 팩토리의 예시가 있습니다.

  1. 토큰 팩토리: 대체 가능한 토큰 컨트랙트를 생성하는 팩토리입니다.
  2. . 일반 팩토리: 기부 컨트랙트를 생성하지만, 배포하는 컨트랙트를 변경할 수 있는 팩토리입니다.
정보

이 페이지에서는 기부 팩토리에 초점을 맞추고 있습니다. 토큰 팩토리에 대해 자세히 알아보려면 레퍼지토리를 확인하세요.


일반 팩토리

일반 팩토리는 다음과 같은 컨트랙트 팩토리를 제공합니다.

  1. 자신의 하위 계정을 생성하고 컨트랙트를 배포합니다 (create_factory_subaccount_and_deploy).
  2. update_stored_contract 메서드를 사용하여 저장된 컨트랙트를 변경할 수 있습니다.
contract/src/deploy.rs
loading...

빠른 시작

  1. rust를 설치했는지 확인하세요.
  2. NEAR CLI를 설치하세요.

팩토리 구축 및 배포

다음을 실행하여 NEAR 테스트넷에서 컨트랙트를 자동으로 컴파일하고 배포할 수 있습니다.

./deploy.sh

완료되면 neardev/dev-account 파일을 확인하여 컨트랙트가 배포된 주소를 찾습니다.

cat ./neardev/dev-account
# e.g. dev-1659899566943-21539992274727

저장된 컨트랙트를 하위 게정에 배포

create_factory_subaccount_and_deploy는 팩토리의 하위 계정을 만들고, 여기에 저장된 컨트랙트를 배포합니다.

near call <factory-account> create_factory_subaccount_and_deploy '{ "name": "sub", "beneficiary": "<account-to-be-beneficiary>"}' --deposit 1.24 --accountId <account-id> --gas 300000000000000

그러면 이는 donation 컨트랙트가 배포될 sub.<factory-account>를 생성할 것입니다.

near view sub.<factory-account> get_beneficiary
# expected response is: <account-to-be-beneficiary>

저장된 컨트랙트 업데이트

update_stored_contract를 통해 팩토리가 저장하는 컴파일된 컨트랙트을 변경할 수 있습니다.

이 메서드의 흥미로운 점은, 선언된 매개 변수가 없지만 바이트 스트림으로 저장할 새 컨트랙트라는 입력을 받는다는 것입니다.

이를 사용하려면 저장하려는 컨트랙트를 base64 표현으로 바꾸고, 결과를 메서드에 대한 입력으로 전달해야 합니다.

# Use near-cli to update stored contract
export BYTES=`cat ./src/to/new-contract/contract.wasm | base64`
near call <factory-account> update_stored_contract "$BYTES" --base64 --accountId <factory-account> --gas 30000000000000

이는 호출의 인자가 JSON 객체이거나 String Buffer이기 때문에 작동 가능합니다.


팩토리 - 개념 & 한계

팩토리는 흥미로운 개념입니다. 여기서는 구현 측면과 제한 사항에 대해 자세히 설명합니다.


자동으로 계정 생성

NEAR 계정은 자신의 하위 계정만 만들 수 있으므로, factory는 자체 하위 계정에서만 컨트랙트를 만들고 배포할 수 있습니다.

이는 다음을 의미합니다.

  1. 팩토리는 sub.factory.testnet를 생성하고, 여기에 컨트랙트를 배포할 수 있습니다.
  2. 팩토리는 predecessor의 하위 계정을 만들 수 없습니다.
  3. 새 계정(예: account.testnet)을 만들 수 있지만, 거기에 컨트랙트를 배포할 순 없습니다.

factory.testnetsub.factory.testnet를 생성할 수 있지만, 생성 후에는 제어할 수 없다는 점을 기억하는 것이 중요합니다.


업데이트 메서드

update_stored_contracts는 매우 짧게 구현되어 있습니다.

#[private]
pub fn update_stored_contract(&mut self) {
self.code = env::input().expect("Error: No input").to_vec();
}

처음 볼 때 메서드는 입력 매개 변수를 사용하지 않는 것처럼 보이지만,코드의 유일한 행이 env::input()에서 읽히는 것을 볼 수 있습니다. 여기에서는, update_stored_contract입력 역직렬화 단계를 우회하는 일이 발생합니다.

update_stored_contract(&mut self, new_code: Vec<u8>)를 구현해서, 컴파일된 코드를 Vec<u8>로 저장할 수도 있지만, 그러면 컨트랙트에서 다음과 같은 일이 발생합니다.

  1. 입력에서 new_code 변수가 역직렬화됩니다.
  2. 이를 필터링하여, 정확하게 구축되었는지 확인합니다.

입력 데이터의 큰 스트림을 처리할 때(저장할 컴파일된 파일과 마찬가지로 wasm) 입력을 역직렬화/확인하는 이 프로세스는 트랜잭션에 대해 전체 가스를 소모합니다.