본문으로 건너뛰기

"Pectra" 태그로 연결된 1개 게시물개의 게시물이 있습니다.

모든 태그 보기

Pectra 이후의 EIP-7702: 이더리움 앱 개발자를 위한 실용 가이드북

· 약 8분
Dora Noda
Software Engineer

2025년 5월 7일, 이더리움의 Pectra 업그레이드(Prague + Electra)가 메인넷에 적용되었습니다. 개발자에게 가장 눈에 띄는 변화 중 하나는 EIP-7702로, 이는 외부 소유 계정(EOA)이 자금을 마이그레이션하거나 주소를 변경하지 않고도 스마트 컨트랙트 로직을 "마운트"할 수 있게 합니다. 지갑, dapp, 또는 릴레이어를 구축한다면, 이것은 스마트 계정 UX로의 더 간단한 경로를 제공합니다.

아래는 간결한 구현 중심 가이드입니다: 실제로 배포된 것, 7702가 어떻게 작동하는지, 순수 ERC-4337보다 언제 선택해야 하는지, 그리고 오늘 적용할 수 있는 복사-붙여넣기 가능한 스캐폴드.


실제로 배포된 것

  • EIP-7702는 Pectra의 최종 범위에 포함되어 있습니다. Pectra 하드포크의 메타 EIP는 공식적으로 포함된 변경사항 중 7702를 나열합니다.
  • 활성화 세부사항: Pectra는 2025년 5월 7일 에포크 364032에서 메인넷에 활성화되었으며, 모든 주요 테스트넷에서의 성공적인 활성화를 따랐습니다.
  • 툴체인 주의사항: Solidity v0.8.30은 Pectra 호환성을 위해 기본 EVM 타겟을 prague로 업데이트했습니다. 특히 특정 버전을 고정하는 경우 컴파일러와 CI 파이프라인을 업그레이드해야 합니다.

EIP-7702—어떻게 작동하는가 (세부사항)

EIP-7702는 새로운 트랜잭션 유형과 EOA가 실행 로직을 스마트 컨트랙트에 위임할 수 있는 메커니즘을 도입합니다.

  • 새로운 트랜잭션 유형 (0x04): 타입-4 트랜잭션은 authorization_list라는 새로운 필드를 포함합니다. 이 리스트는 하나 이상의 인증 튜플—(chain_id, address, nonce, y_parity, r, s)—을 포함하며, 각각은 EOA의 개인키로 서명됩니다. 이 트랜잭션이 처리되면, 프로토콜은 EOA의 코드 필드에 위임 표시자를 씁니다: 0xef0100 || address. 그 순간부터, EOA에 대한 모든 호출은 지정된 address(구현)로 프록시되지만, EOA의 저장소 및 잔고 컨텍스트 내에서 실행됩니다. 이 위임은 명시적으로 변경될 때까지 활성 상태를 유지합니다.
  • 체인 범위: 인증은 chain_id를 제공하여 체인별이 될 수도 있고, chain_id0으로 설정된 경우 모든 체인에 적용될 수도 있습니다. 이를 통해 사용자가 각각에 대해 새 인증에 서명할 필요 없이 여러 네트워크에 동일한 구현 컨트랙트를 배포할 수 있습니다.
  • 취소: EOA를 원래의 프로그래밍 불가능한 동작으로 되돌리려면, 구현 address제로 주소로 설정된 다른 7702 트랜잭션을 보내기만 하면 됩니다. 이렇게 하면 위임 표시자가 지워집니다.
  • 셀프 스폰서 vs. 릴레이: EOA는 타입-4 트랜잭션을 스스로 제출할 수도 있고, 제3자 릴레이어가 EOA를 대신하여 제출할 수도 있습니다. 후자는 가스없는 사용자 경험을 만드는 데 일반적입니다. 논스 처리는 방법에 따라 약간 다르므로, 이 구별을 올바르게 관리하는 라이브러리를 사용하는 것이 중요합니다.

보안 모델 변경: 원래 EOA 개인키가 여전히 존재하기 때문에, 새로운 7702 트랜잭션을 제출하여 위임을 변경함으로써 항상 스마트 컨트랙트 규칙(소셜 복구나 지출 한도 등)을 재정의할 수 있습니다. 이것은 근본적인 변화입니다. tx.origin에 의존하여 호출이 EOA에서 왔는지 확인하는 컨트랙트는 7702가 이러한 가정을 깨뜨릴 수 있으므로 재감사가 필요합니다. 이에 따라 플로우를 감사하세요.


7702 또는 ERC-4337? (그리고 언제 결합할 것인가)

EIP-7702와 ERC-4337 모두 계정 추상화를 가능하게 하지만, 서로 다른 요구를 충족합니다.

  • EIP-7702를 선택해야 할 때…
    • 사용자에게 자금을 마이그레이션하거나 주소를 변경하도록 강요하지 않고 기존 EOA에 즉시 스마트 계정 UX를 제공하고 싶을 때.
    • 새로운 기능으로 점진적으로 업그레이드할 수 있는 체인 간 일관된 주소가 필요할 때.
    • 계정 추상화로의 전환을 단계별로 진행하고 싶을 때, 간단한 기능부터 시작하여 시간이 지나면서 복잡성을 추가하는.
  • 순수 ERC-4337을 선택해야 할 때…
    • 제품이 첫날부터 완전한 프로그래밍 가능성과 복잡한 정책 엔진(멀티시그, 고급 복구 등)을 필요로 할 때.
    • 기존 EOA가 없는 새로운 사용자를 위해 구축하는 경우, 새로운 스마트 계정 주소와 관련 설정이 허용되는.
  • 둘을 결합: 가장 강력한 패턴은 둘 다 사용하는 것입니다. EOA는 7702 트랜잭션을 사용하여 ERC-4337 지갑 구현을 로직으로 지정할 수 있습니다. 이렇게 하면 EOA가 4337 계정처럼 동작하게 되어, 기존 4337 인프라에 의해 번들링되고, 페이마스터에 의해 후원되며, 처리될 수 있습니다—사용자가 새 주소를 필요로 하지 않으면서 말이죠. 이는 EIP 저자들이 명시적으로 권장하는 전진 호환 경로입니다.

적용 가능한 최소 7702 스캐폴드

구현 컨트랙트와 이를 활성화하는 클라이언트 측 코드의 실용적인 예제는 다음과 같습니다.

1. 작고 감사 가능한 구현 컨트랙트

이 컨트랙트 코드는 지정되면 EOA의 컨텍스트 내에서 실행됩니다. 작고 감사 가능하게 유지하고, 업그레이드 메커니즘 추가를 고려하세요.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/// @notice EIP-7702를 통해 지정될 때 EOA 컨텍스트에서 호출을 실행합니다.
contract DelegatedAccount {
// 다른 컨트랙트와의 충돌을 피하기 위한 고유한 저장소 슬롯.
bytes32 private constant INIT_SLOT =
0x3fb93b3d3dcd1d1f4b4a1a8db6f4c5d55a1b7f9ac01dfe8e53b1b0f35f0c1a01;

event Initialized(address indexed account);
event Executed(address indexed to, uint256 value, bytes data, bytes result);

modifier onlyEOA() {
// 선택사항: 특정 함수를 호출할 수 있는 사람을 제한하는 검사 추가.
_;
}

function initialize() external payable onlyEOA {
// EOA의 저장소에 간단한 일회성 초기화 플래그 설정.
bytes32 slot = INIT_SLOT;
assembly {
if iszero(iszero(sload(slot))) { revert(0, 0) } // 이미 초기화된 경우 revert
sstore(slot, 1)
}
emit Initialized(address(this));
}

function execute(address to, uint256 value, bytes calldata data)
external
payable
onlyEOA
returns (bytes memory result)
{
(bool ok, bytes memory ret) = to.call{value: value}(data);
require(ok, "CALL_FAILED");
emit Executed(to, value, data, ret);
return ret;
}

function executeBatch(address[] calldata to, uint256[] calldata value, bytes[] calldata data)
external
payable
onlyEOA
{
uint256 n = to.length;
require(n == value.length && n == data.length, "LENGTH_MISMATCH");
for (uint256 i = 0; i < n; i++) {
(bool ok, ) = to[i].call{value: value[i]}(data[i]);
require(ok, "CALL_FAILED");
}
}
}

2. viem으로 EOA에 컨트랙트 지정 (타입-4 tx)

viem과 같은 현대적 클라이언트는 인증에 서명하고 타입-4 트랜잭션을 보내는 내장 헬퍼를 가지고 있습니다. 이 예제에서 relayer 계정은 eoa를 업그레이드하기 위한 가스를 지불합니다.

import { createWalletClient, http, encodeFunctionData } from "viem";
import { sepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { abi, implementationAddress } from "./DelegatedAccountABI";

// 1. 릴레이어(가스 후원)와 업그레이드될 EOA 정의
const relayer = privateKeyToAccount(process.env.RELAYER_PK as `0x${string}`);
const eoa = privateKeyToAccount(process.env.EOA_PK as `0x${string}`);

const client = createWalletClient({
account: relayer,
chain: sepolia,
transport: http(),
});

// 2. EOA가 구현 컨트랙트를 가리키는 인증에 서명
const authorization = await client.signAuthorization({
account: eoa,
contractAddress: implementationAddress,
// EOA 자체가 이를 보내는 경우 추가할 것: executor: 'self'
});

// 3. 릴레이어가 EOA의 코드를 설정하고 initialize() 호출하기 위해 타입-4 트랜잭션을 보냄
const hash = await client.sendTransaction({
to: eoa.address, // 목적지는 EOA 자체
authorizationList: [authorization], // 새로운 EIP-7702 필드
data: encodeFunctionData({ abi, functionName: "initialize" }),
});

// 4. 이제 EOA는 추가 인증 없이 새로운 로직을 통해 제어할 수 있습니다
// 예를 들어, 트랜잭션을 실행하려면:
// await client.sendTransaction({
// to: eoa.address,
// data: encodeFunctionData({ abi, functionName: 'execute', args: [...] })
// });

3. 위임 취소 (일반 EOA로 되돌리기)

업그레이드를 취소하려면, EOA가 제로 주소를 구현으로 지정하는 인증에 서명하고 다른 타입-4 트랜잭션을 보내도록 합니다. 이후 eth_getCode(eoa.address) 호출은 빈 바이트를 반환해야 합니다.


프로덕션에서 작동하는 통합 패턴

  • 기존 사용자를 위한 제자리 업그레이드: dapp에서 사용자가 Pectra 호환 네트워크에 있는지 감지합니다. 그렇다면 일회성 인증 서명을 트리거하는 선택적 "계정 업그레이드" 버튼을 표시합니다. 오래된 지갑을 가진 사용자를 위한 대체 경로(클래식 approve + swap 등)를 유지합니다.
  • 가스리스 온보딩: 초기 타입-4 트랜잭션을 후원하기 위해 릴레이어(백엔드 또는 서비스)를 사용합니다. 지속적인 가스리스 트랜잭션의 경우, 기존 페이마스터와 공개 멤풀을 활용하기 위해 ERC-4337 번들러를 통해 사용자 작업을 라우팅합니다.
  • 크로스체인 롤아웃: 모든 체인에서 동일한 구현 컨트랙트를 지정하기 위해 chain_id = 0 인증을 사용합니다. 그런 다음 애플리케이션 로직 내에서 체인별로 기능을 활성화하거나 비활성화할 수 있습니다.
  • 관찰가능성: 백엔드는 타입-4 트랜잭션을 인덱싱하고 어떤 EOA가 업그레이드되었는지 추적하기 위해 authorization_list를 파싱해야 합니다. 트랜잭션 후에는 eth_getCode를 호출하고 EOA의 코드가 이제 위임 표시자(0xef0100 || implementationAddress)와 일치하는지 확인하여 변경을 검증합니다.

위협 모델 및 주의사항 (이것을 건너뛰지 마세요)

  • 위임은 지속적입니다: EOA의 구현 컨트랙트 변경을 표준 스마트 컨트랙트 업그레이드와 같은 심각성으로 다루세요. 이는 감사, 명확한 사용자 커뮤니케이션, 이상적으로는 옵트인 플로우를 필요로 합니다. 사용자에게 조용히 새로운 로직을 푸시하지 마세요.
  • tx.origin 지뢰: msg.sender == tx.origin을 사용하여 호출이 EOA에서 직접 왔는지 확인하는 로직은 이제 잠재적으로 취약합니다. 이 패턴은 EIP-712 서명이나 명시적 허용 목록과 같은 더 견고한 검사로 대체되어야 합니다.
  • 논스 수학: EOA가 자체 7702 트랜잭션을 후원하는 경우(executor: 'self'), 인증 논스와 트랜잭션 논스가 특정한 방식으로 상호작용합니다. 재생 문제를 피하기 위해 이를 올바르게 처리하는 라이브러리를 항상 사용하세요.
  • 지갑 UX 책임: EIP-7702 사양은 dapp이 사용자에게 임의의 지정에 서명하도록 요청해서는 안 된다고 경고합니다. 제안된 구현을 검증하고 안전한지 확인하는 것은 지갑의 책임입니다. 지갑 매개 보안의 이 원칙에 맞춰 UX를 설계하세요.

7702가 명확한 승리인 경우

  • DEX 플로우: 멀티스텝 approveswapexecuteBatch 함수를 사용하여 단일 클릭으로 결합할 수 있습니다.
  • 게임 및 세션: 사용자가 새로운 지갑을 생성하고 자금을 조달할 필요 없이 제한된 시간이나 범위에서 세션 키와 같은 권한을 부여합니다.
  • 기업 및 핀테크: 후원된 트랜잭션을 활성화하고 회계 및 신원을 위해 모든 체인에서 동일한 기업 주소를 유지하면서 맞춤 지출 정책을 적용합니다.
  • L2 브리지 및 인텐트: 다른 네트워크에서 일관된 EOA 신원을 가진 더 부드러운 메타 트랜잭션 플로우를 생성합니다.

이러한 사용 사례는 ERC-4337이 약속한 동일한 핵심 이익을 나타내지만, 이제 단일 인증으로 모든 기존 EOA에서 사용할 수 있습니다.


배송 체크리스트

프로토콜

  • 노드, SDK, 인프라 제공업체가 타입-4 트랜잭션과 Pectra의 "prague" EVM을 지원하는지 확인.
  • 새로운 트랜잭션에서 authorization_list 필드를 파싱하도록 인덱서와 분석 도구 업데이트.

컨트랙트

  • 필수 기능(배칭, 취소 등)을 가진 최소한의 감사된 구현 컨트랙트 개발.
  • 메인넷에 배포하기 전에 테스트넷에서 취소재지정 플로우를 철저히 테스트.

클라이언트

  • 클라이언트 측 라이브러리(viem, ethers 등) 업그레이드 및 signAuthorizationsendTransaction 함수 테스트.
  • 셀프 스폰서 및 릴레이 트랜잭션 경로 모두 논스재생을 올바르게 처리하는지 확인.

보안

  • 컨트랙트에서 tx.origin에 기반한 모든 가정을 제거하고 더 안전한 대안으로 교체.
  • 사용자 주소에서 예상치 못한 코드 변경을 감지하고 의심스러운 활동에 대해 알려주는 배포 후 모니터링 구현.

결론: EIP-7702는 이미 사용 중인 수백만 개의 EOA에 대한 스마트 계정 UX로의 저마찰 진입로를 제공합니다. 작고 감사된 구현으로 시작하고, 가스리스 설정을 위해 릴레이 경로를 사용하며, 취소를 명확하고 쉽게 만들면, 전체 계정 추상화의 90% 이익을 제공할 수 있습니다—주소 변경과 자산 마이그레이션의 고통 없이.