본문으로 건너뛰기
전체 글

같은 자산을 Native에서 승인하고 EVM에서 사용하기

· 약 6분
Bankware Global Engineering

지갑에서 직접 보낼 수 있는 자산을 업무 계약에서도 사용하고 싶다. 사용자가 허용한 수량 안에서 계약이 지급을 처리하고, 업무가 실패하면 자산 이전도 함께 취소되는 흐름이다. 실행 방식이 바뀔 때마다 별도 잔액이나 승인 기록을 관리해야 한다면 하나의 원장을 쓰는 이점은 작아진다.

nigo-protocol은 같은 Native Asset을 소유자가 직접 보내거나, Native 프로그램과 EVM 계약을 통해 사용할 수 있게 한다. 통합 자산 설계가 자산의 공통 모델을 마련했다면, 실행 영역의 연결은 그 모델을 실제 업무에서 활용하게 한다. 한 경로에서 승인한 권한을 다른 경로가 확인하고, 함께 실행한 업무의 성공과 실패를 같은 상태에 반영하는 것이다.

EVM 호환을 다룬 글에서는 기존 계약 코드와 개발 도구를 이어 쓰는 이점을 살펴봤다. 이번에는 EVM 업무 계약이 원장의 Native 자산을 사용하는 과정을 따라가 보자.

같은 출발점에서 두 가지 사용법을 비교한다​

자산 X를 A가 100개, B가 0개 보유하고 있다. P는 지급 업무를 수행하는 EVM 계약이며, 아직 A에게 사용 권한을 받지 않았다. 이 글은 다른 글의 전송 결과를 이어받지 않고 이 상태에서 독립적으로 시작한다.

X는 소유자의 직접 전송이 허용되고 현재 활성 상태인 표준 자산으로 둔다. 필요한 정책과 EVM 연결 계약은 이미 준비됐으며 발행·소각·정책 변경은 하지 않는다. 100·20·30은 설명용 수치다. 수수료 금액은 0으로 두고 실행량 한도와 서명·입력 조건은 충족한다고 가정한다. 거래에 필요한 NIGO 재원은 업무 자산 X와 별도로 준비한다.

첫 번째 방법은 A가 X 20개를 B에게 직접 보내는 것이다. Direct Cell 거래는 A가 소비할 셀과 새로 만들 셀을 제시하고, 원장은 소유권·서명·현재 자산의 직접 전송 허용 조건과 수량 보존을 검사한다. 성공하면 A에게 80개, B에게 20개가 남는다. P의 승인은 여전히 0이다.

자산 정책의 가상 머신은 호출하지 않는다. Direct는 정책 실패 시 우회로가 아니라 소유자의 전송 권한을 공통 규칙으로 확인하는 정식 실행 방식이다.

두 번째 방법은 P에 일부 사용 권한을 주고 업무를 맡기는 것이다. 이제 다시 A=100, B=0, 승인=0에서 시작한다. 앞의 직접 전송 후에 이어지는 거래가 아니다.

승인은 Native에서, 사용은 EVM 업무에서​

A가 별도의 Native 거래로 P에 X 30개의 사용을 승인한다. 그 거래가 확정되면 A의 잔액은 여전히 100이고 B는 0이다. 승인은 X를 P에게 미리 옮기는 행위가 아니다. P가 A의 자산을 사용할 수 있는 한도인 allowance를 기록한다.

이후 EVM 거래가 P의 업무 함수를 호출한다. P는 요청자와 지급 대상이 업무 조건에 맞는지 확인한 다음, X의 연결 계약인 adapter에 transferFrom(A, B, 20)을 요청한다. 이 adapter에는 X를 가리키는 정보가 고정되어 있고, 현재 X에 연결된 Native 정책으로 요청을 전달한다.

정책은 A가 P에 부여한 승인 30을 확인한다. 사용량 20이 허용 범위 안에 있고 필요한 입력과 자산 규칙도 충족되면, 잔액 이전과 승인 차감을 함께 반영한다. 결과는 A=80, B=20, 남은 승인=10이다. X의 총량은 100으로 유지된다.

Native 거래: A가 P에 30 승인 → 확정
잔액 A=100, B=0 / 승인=30
↓
EVM 거래: P가 X의 adapter에 20 이전 요청
↓
X의 Native 정책 검증 → 공통 원장에 반영
잔액 A=80, B=20 / 승인=10

Native에서 만든 승인과 EVM에서 읽는 승인은 같은 기록이다. 성공한 뒤 A가 다시 Native 거래로 남은 승인을 0으로 바꾸면 잔액 80/20은 유지되고, P의 다음 위임 사용은 거절된다. EVM 쪽에 예전 한도 10의 복사본이 남아 따로 사용되는 구조가 아니다.

지갑은 Native 요청으로 권한을 관리하고 업무 개발자는 EVM 계약으로 절차를 구성하면서, 같은 자산과 승인 상태를 사용할 수 있다.

같은 상태를 사용해도 누구의 권한인지는 확인한다​

adapter는 요청을 전달하는 통로이며, 그 주소를 호출했다는 사실만으로 자산을 쓸 권한이 생기지는 않는다. 이 예제에서 정책이 확인할 사용자는 실제로 adapter를 호출한 계약 P다. EVM 거래에 처음 서명한 주소를 P 대신 사용하지 않는다.

이 구분이 없으면 A가 어떤 계약을 호출했다는 이유만으로 그 계약이 A의 직접 소유 권한까지 행사할 수 있다. nigo-protocol은 실제 호출 관계와 adapter 코드를 확인하고, 그 호출자에게 현재 정책이 허용하는 효과만 승인한다.

P 역시 외부 요청자와 수신자를 업무 규칙에 맞게 검사해야 한다. P가 승인받았다는 이유로 누구나 원하는 주소로 지급하게 만들 수는 없다.

또한 adapter는 임의의 ERC-20 계약을 자동으로 Native Asset으로 바꾸지 않는다. 이 글의 X는 처음부터 Native Asset이며 P는 X를 사용하는 업무 계약이다. EVM 함수 호출의 상태 변경에서 설명한, EVM 계약 자체의 저장소에 토큰 잔액을 두는 방식과는 자산 상태를 보관하는 위치가 다르다.

자산 이전 뒤 업무가 실패하면​

P가 X 20개를 B에게 이전한 뒤, 남은 업무 조건을 충족하지 못해 호출 전체를 취소했다고 하자. EVM의 REVERT는 해당 호출의 변경을 되돌린다. 여기서 Native 자산의 이전만 살아남으면 업무는 실패했는데 자산은 지급된 결과가 된다.

이를 막기 위해 adapter를 통한 Native 변경도 EVM 호출의 취소 범위에 포함된다. 먼저 임시 상태에서 처리하고 상위 호출까지 성공해야 반영한다. 상위 호출이 취소되면 자산 이전, 승인 차감, 그에 따른 이벤트도 함께 사라진다.

아래 두 결과는 Native 승인 30이 이미 확정된 같은 상태에서 갈라지는 대안이다.

EVM 업무 결과A의 XB의 XP의 남은 승인
호출 전100030
이전과 상위 업무 모두 성공802010
이전 후 상위 업무가 REVERT100030

실패한 분기에서 승인 30이 남는 이유는 그 승인이 앞선 별도 거래에서 이미 확정됐기 때문이다. 이번 호출을 취소하는 것이 과거의 승인 거래까지 취소하지는 않는다. 반대로 성공한 80/20/10 상태가 확정된 뒤 새 거래가 실패했다면 복귀점도 80/20/10이다.

업무 변경의 취소가 거래 처리 이력 전체를 지운다는 뜻은 아니다. 바깥 EVM 거래의 nonce와 수수료 정산, 실패 결과는 거래 규칙에 따라 처리된다. 계정의 실행 코드를 지정하는 Type-4 거래에서는 유효한 승인 설정도 업무 실패 후 남을 수 있다. adapter 내부에서는 별도 Native 서명 거래나 별도 Native 수수료를 만들지 않고, 그 실행 비용을 바깥 EVM 거래의 실행량에 포함한다. 실패한 거래에서 남는 효과에서는 실행 전 거절, 내부 호출 실패, 전체 되돌림을 비교하며 이 경계를 더 자세히 살펴본다.

공통 모델을 실제 사용으로 잇는다​

표준 자산 회귀에서는 Native와 EVM 사이의 승인 사용, 실제 계약 호출자의 권한, 상위 실패 시 잔액·승인·이벤트 복귀를 확인했다. 조합형 정책의 실제 실행 시험에서도 서명된 Type-2·Type-4 거래 안에서 Native 변경을 처리하고, 상위 실패와 바깥 거래의 수수료·nonce를 구분한다.

공개 RPC와 실제 SDK를 사용한 고정 실행 파일의 기능 인수에는 Native에서 승인한 뒤 ethers로 사용하는 흐름과, SDK에서 만든 승인을 Native 거래로 소비하는 흐름이 포함됐다. 이 근거는 확인한 자산 구성과 호출 경로의 연결을 보여준다. 모든 계약 조합이나 운영 성능까지 보장하는 결과는 아니다.

NIGO도 같은 자산 모델에 속하지만 역할과 진입점은 구분된다. 예약된 자산 식별자와 수수료·EVM value 역할을 가지며, 현재 NIGO의 allowance 승인과 사용은 Native 경로에서 지원한다. 따라서 X의 EVM adapter 예제를 NIGO의 allowance에도 그대로 적용할 수 있다고 읽어서는 안 된다.

여기까지는 유효한 입력을 마련할 수 있다고 가정했다. 그런데 잔액이 충분하고 승인도 받았는데, 보유 자산이 수많은 작은 셀에 나뉘어 있어 송금이 막힌다면 어떨까? 자산을 실제로 쓸 수 있으려면 총량을 아는 것에 더해, 한 번의 거래에서 소비할 입력을 찾을 수 있어야 한다. 다음 글에서는 이 차이가 작은 송금을 막았던 사례를 살펴본다.