Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEAR Cross Contract 리서치 #32

Open
happyhappy-jun opened this issue Jul 17, 2022 · 1 comment
Open

NEAR Cross Contract 리서치 #32

happyhappy-jun opened this issue Jul 17, 2022 · 1 comment
Assignees

Comments

@happyhappy-jun
Copy link
Contributor

금주 개발 준비 기간 팀 배분입니다.

Token 모델 (FT, NFT) (ex. ERC20 link token specification) (준수, 해빈, 경민, 승준, 은성)
Cross-Contract interaction (영호, 병준) (다음 미팅까지)

리서치 방법

  • wiki 1인당 페이지 하나씩 만들어서
    • 다른 사람이 했더라도 없다고 생각하고 리서치 진행
  • 개념 정의
  • Specification (특히 토큰)
  • 이해를 돕기 위한 예시 (ex. 코드)
  • 해당 주제와 관련된 보안 관련된 내용들
@0k1019
Copy link
Contributor

0k1019 commented Sep 19, 2022

Cross Contract Call

Contract내에서 배포되어있는 Contract와 Query 또는 Interact 하는 것을 말한다.
ex) 배포되어있는 light client에 cross contract call을 통해서 treasury의 token 사용처, nft의 mint 가능 여부 등을 확인한 뒤 실행시킬 수 있다.

특징

  • Transaction status의 성공, 실패는 첫번째 함수가 실행될 때 결정된다. ContractB.methodB 혹은 ContractA.methodACb 함수가 실패하더라도, 해당 Transaction은 성공이다. 따라서 예상되는 실패 경우에 따라서 적절한 rollback이 필요하다. rollback 코드는 ContractA.methodACb에 적혀있어야 하고, 실패할수 없도록 코드를 작성해야한다. 그렇지 않으면 Smart Contract의 상태는 불안하게 된다.

  • Cross-contract call은 gas와 함께 사용되어야 한다. 총 사용가능한 가스량은 사용자가 Transaction을 호출할 때 알 수 있고, contract 체인 상에서 분배된다. 예를 들어 15TGas를 유저가 보냈다면 5TGas는 ContractA에서 사용하고, 나머지는 ContractB로 가게된다. 사용되지 않은 가스들은 유저에게 환불된다.

  • NEAR tokens를 사용하여 cross contract calls를 할 수 있다. gas와 다르게 동작한다. predecessor 계정에서 가져온 deposit을 활용한다. 따라서 유저는 deposit을 지불할 필요가 없고, contract는 자신의 계정에서 가져온 토큰들을 가지고 있다. 또한, cross-contract call의 실패는 Transaction의 실패가 아니기 때문에 자동으로 환불되지 않는다. 모든 환불은 rollback코드에 명확히 명시해야한다.

구현 예시

  // Public - query external greeting
  pub fn query_greeting(&self) -> Promise {
    // Create a promise to call HelloNEAR.get_greeting()
    let promise = hello_near::ext(self.hello_account.clone())
      .with_static_gas(Gas(5*TGAS))
      .get_greeting();
    
    return promise.then( // Create a promise to callback query_greeting_callback
      Self::ext(env::current_account_id())
      .with_static_gas(Gas(5*TGAS))
      .query_greeting_callback()
    )
  }

call back 예시

  #[private] // Public - but only callable by env::current_account_id()
  pub fn query_greeting_callback(&self, #[callback_result] call_result: Result<String, PromiseError>) -> String {
    // Check if the promise succeeded by calling the method outlined in external.rs
    if call_result.is_err() {
      log!("There was an error contacting Hello NEAR");
      return "".to_string();
    }

    // Return the greeting
    let greeting: String = call_result.unwrap();
    greeting
  }

구현 주의 사항

  • 외부 contract 주소를 set 해야하는 함수 혹은 init 필요

주의 사항

  • Fallback 프로세스를 잘만들자. reentrancy attacks 주의

참고사항

  • 배포된 contract의 view method일 경우에도 Gas 필요

example

실행 시 주의 사항
배포되어 있는 contract 주소 설정 필요

near call dev-1662608733396-56839622990756 init '{"hello_account":"dev-1663557297447-86858260607503"}' --accountId dev-1662608733396-56839622990756

"hello_account" : "배포되어있는 contact 주소"
실행 예시
cross contract call

near call dev-1662608733396-56839622990756 query_greeting --accountId dev-1662608733396-56839622990756

--accountId를 자신의 지갑 주소로 변경시 gas fee 빠져나감

[Ref]

TODO

fall back 코드 작성시 user에게 deposit 돌려주는 코드 작성 필요.
https://nomicon.io/RuntimeSpec/Scenarios/CrossContractCall
https://medium.com/block-imperium-games/making-cross-contract-calls-with-near-e19aa2c91ffe
https://docs.near.org/tutorials/crosswords/intermediate/overview#cross-contract-calls
https://docs.near.org/tutorials/crosswords/intermediate/cross-contract-calls#cross-contract-calls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants