티스토리 뷰
Authorization_list의 튜플 값 검증 및 서명 복원 과정, EIP7702 test in Geth & 테스트넷에서의 동작 확인
g0rani 2026. 8. 26. 21:59EIP-7702에서 등장한 새로운 트랜잭션 타입 0x04에 추가된 authorization_list의 튜플의 서명을 복원하는 과정을 geth 코드로 살펴보겠다. 클라이언트 노드는 서명을 복원함으로써 authority(EOA)를 얻고 해당 계정에 코드 슬롯에 위임 지시자(deligation indicator)를 기록한다. 사실 EIP-7702 표준 하나를 이해하는데 여기까지 볼 필요는 없지만, 궁금하기도하고 geth 분석도 할겸 겸사겸사 살펴보겠다. 버전은 geth v1.17.5를 기준으로 한다
0. 튜플이란? (튜플 서명 과정)
트랜잭션 SetCodeTx.AuthList에 들어있는 튜플이다. 다음과 같이 구성되어 있다.
서명은 SigHash()로 keccak256(MAGIC(0x05) || rlp([chain_id, address, nonce]))을 수행하고, SignSetCode() 함수를 호출해 완성한다.

1. type 4 tx에서 복원되는 서명 종류
auth_list를 추가한 type 4 tx의 경우 복원해야하는 서명 종류가 크게 2가지로 나뉜다.
|
|
바깥 tx | SetCodeAuthorization 튜플 |
|
필드
|
SetCodeTx의 V, R, S
|
각 SetCodeAuthorization의 V, R, S (yParity)
|
|
복원 함수
|
types.Sender
|
SetCodeAuthorization.Authority
|
|
결과
|
msg.From (tx.origin)
|
지시자를 받을 authority
|
|
실패
|
트랜잭션 전체 무효
|
그 튜플만 skip
|
2. 튜플로부터 authority 값 복원
EVM이 아니라 executecall안의 Authority()가 ecrecover로 authority(EOA)주소를 확보한다. 트랜잭션이 노드에 들어오고 검증되는 과정은 생략하고, 전체적인 콜스택은 다음과 같다. 순서대로 설명해보겠다.
execute(트랜잭션 진입점)
-> executeCall
-> applyAuthorizations
-> applyAuthorization // 튜플마다 시행
-> validateAuthorization
-> auth.Authority() // EOA 주소 복원
-> SetNonce / SetCode
-> evm.Call
먼저 복사해둔 auth_list를 인자로 넘겨 applyAuthorizations()를 호출한다.

applyAuthorizations()는 auths를 돌면서 applyAuthorization()을 호출한다. 서명 실패·체인 ID 불일치·nonce 불일치는 그 튜플만 건너뛰고 다음으로 진행한다. 전체 tx가 revert되지 않는다.

applyAuthorization()의 첫 줄은 validateAuthorization()를 호출하는데, 이안에서 chaind_id, nonce값 확인과 서명 복원이 이루어진다.

validateAuthorization()의 전체 과정은 다음과 같다.

3번 auth.Authority()로 authority 주소를 확보하는 과정은 다음과 같다.
3. Deligation indicator(위임 지시자) 기록
다시 applyAuthorization()으로 돌아와서, authority 주소를 확보했으니 위임 지시자를 authority 코들 슬롯에 기록할 차례다.

3. TestEIP7702
setCode 트랜잭션이 EOA에 위임 지시자를 쓰고, 위임 컨트랙트를 따라 call이 실제로 실행되는지를 검증하는 테스트를 TestEIP7702를 실행해보자. 테스트 전체코드는 요기에
테스트에서는 다음 세가지를 확인한다.
- addr1(EOA)가 컨트랙트 aa 위임
- addr2(EOA)가 컨트랙트 bb 위임
- addr2 storage slot 0x42에 값 0x42 기록 확인 (위임된 bb 코드가 addr2 context에서 실행되었음을 확인)
테스트에서 진행하는 tx는 addr1이 자신을 call 하는 형태이고 다음과 같이 진행된다.
- 트랜잭션이 addr1을 CALL
- addr1은 aa로 위임 → aa 코드 실행 (CALL addr2, 1 wei)
- addr2는 bb로 위임 → bb 코드 실행 (SSTORE(0x42, 0x42))
- storage는 addr2에 기록됨 (실행 주체가 addr2이기 때문)
먼저 각 EOA에 1ether씩 주고, 컨트랙트에는 코드를 삽입한다.
각 EOA들이 컨트랙트를에 위임하기 위해 2개의 setCodeAuthorization을 만든다.

이후에 SetCodeTx를 만들고 블록에 추가한다.

tx가 정상적으로 실행되었는지 아래 코드를 통해 확인한다.

테스트를 돌려보면 pass한 것을 볼 수 있다.
go test ./core -run '^TestEIP7702$' -count=1 -v
=== RUN TestEIP7702
--- PASS: TestEIP7702 (0.00s)
PASS
ok github.com/ethereum/go-ethereum/core 0.052s
지금까지 geth를 통해 프로토콜 단에서 EIP-7702를 어떻게 적용하는지 살펴봤다. 이제는 테스트넷에서 EOA가 eth-infinitism에서 작성한 EIP7702구현체 Simple7702Account를 위임하는 트랜잭션을 제출하고, 최종상태와 트랜잭션을 살펴보겠다.
먼저 sepolia testnet을 로컬로 fork 한 후에 테스트를 진행하겠다.
anvil --fork-url https://ethereum-sepolia-rpc.publicnode.com
스크립트는 다음과 같이 작성했다. 요청 JSON은 직접 작성하지 않고 viem 라이브러리를 사용했다.
import {
createWalletClient,
createPublicClient,
http,
parseGwei,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { sepolia } from "viem/chains";
// address : 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
const PRIVATE_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80";
// sepolia 테스트넷 로컬 fork
const RPC_URL = "http://127.0.0.1:8545";
// https://github.com/eth-infinitism/account-abstraction/blob/v0.8.0/deployments/ethereum/Simple7702Account.json
const IMPL = "0x4Cd241E8d1510e30b2076397afc7508Ae59C66c9";
// 개인키를 계정 객체로 변환
const eoa = privateKeyToAccount(PRIVATE_KEY);
const transport = http(RPC_URL);
// 체인 조회용 클라이언트
const publicClient = createPublicClient({ chain: sepolia, transport });
// 지갑 객체 생성
const walletClient = createWalletClient({
account : eoa, // 서명 주체
chain : sepolia,
transport : transport,
});
// EOA nonce값 읽어오기
const nonce = await publicClient.getTransactionCount({
address : eoa.address,
});
// 위임 튜플 서명(setCodeAuthorization 서명)
const authorization = await walletClient.signAuthorization({
account : eoa,
// 위임할 코드 주소(Simple7702Account)
contractAddress : IMPL,
chainId : sepolia.id,
// tx sender와 authority가 같은 상황이므로
// 바깥 tx에서 nonce가 먼저 1증가한 것을 고려해야 함
nonce : nonce + 1,
});
console.log("authorization:", authorization);
// type 4 tx 전송
const hash = await walletClient.sendTransaction({
account : eoa,
to : eoa.address,
authorizationList: [authorization],
});
console.log("tx hash:", hash);
// eth_getTransactionByHash 요청
const transaction = await publicClient.getTransaction({
hash: hash,
});
console.log("\n=== transaction info ===");
console.log("transaction:", transaction);
// EOA code 읽어오기
const bytecode = await publicClient.getCode({
address: eoa.address,
});
console.log("\nEOA code:", bytecode);
EOA privatekey는 anvil 테스트 계정을 사용했고, 배포된 eip7702 관련 구현체 주소는 Simple7702Account에서 확인할 수 있다.
스크립트를 돌려본 결과를 같이 살펴보자

트랜잭션 정보도 조회한 결과를 살펴보자. 트랜잭션 타입이 0x04임이 표시되어 있다.
=== transaction info ===
transaction: {
type: 'eip7702',
chainId: 11155111,
nonce: 47818,
gas: 46046n,
maxFeePerGas: 2178393150n,
maxPriorityFeePerGas: 1000000000n,
to: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
value: 0n,
accessList: [],
authorizationList: [
{
address: '0x4cd241e8d1510e30b2076397afc7508ae59c66c9',
chainId: 11155111,
nonce: 47819,
r: '0xbb7455bc8f3185a0efb3e526d55cede18afb6036404064c42a329f0044f65bce',
s: '0x6668d049e1dba23aa7bbdeae1faa55098abad54cf6f2d3b761d1019a4fba165f',
yParity: 1
}
],
input: '0x',
r: '0xb7eca5282a473e3c818782db092830e5c7ee7e6bd6e891c4bdc27e851b10f1f0',
s: '0x43d8596bed9f8cac24b0771c4c81d775acafecdeec4f48e80581573378886a0e',
yParity: 1,
v: 1n,
hash: '0x2a8b25f3af3f33c004b669e6f130d5298b2de33b3ad44f29d6c2612b7b1fb59a',
blockHash: '0x26e6919bc5ea06cac91563cb6d9fb6a320e190a78a3f915dddde06530ff9eae5',
blockNumber: 11583623n,
transactionIndex: 0,
from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
gasPrice: 2104705239n,
maxFeePerBlobGas: undefined,
typeHex: '0x4'
}
EOA의 코드 슬롯 조회 결과에서 위임지시자 형식을 갖춘 것을 볼 수 있다.

References
ethereum/go-ethereum at v1.17.5
GitHub - ethereum/go-ethereum at v1.17.5
Go implementation of the Ethereum protocol. Contribute to ethereum/go-ethereum development by creating an account on GitHub.
github.com
'Web3 > Ethereum' 카테고리의 다른 글
| EOA기반 지갑과 AA기반 스마트 지갑 사용자 흐름 차이점 & AA인프라 시퀀스 다이어그램 (0) | 2026.08.30 |
|---|---|
| EIP-7702: Set Code for EOAs (Add a new tx type that permanently sets the code for an EOA) (0) | 2026.08.24 |
| ERC-4337: Account Abstraction를 활용한 스마트 지갑 생성(Privy + Pimlico) (0) | 2026.08.20 |
| EIP-1599 | 가스 요금 개선안 (0) | 2025.11.04 |
| EIP vs ERC (0) | 2025.11.04 |
- Total
- Today
- Yesterday
- ethereum
- rebase token
- eip1599
- DEFI
- erc4337
- view functions
- storageslot
- MagicNumber
- 계정추상화
- 이더넛
- aderyn
- Delegatecall
- solidity
- oracles
- Blockchain
- 블록구조
- dynamic array slot
- Ethernaut
- 모빌리티 보안
- ERC20
- ethrnaut
- 토큰전송
- eip7702
- price manipulation
- DexTwo
- gaslimit
- 토큰화주식
- type2 transaction
- smart contract
- puzzlewallet
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | ||
| 6 | 7 | 8 | 9 | 10 | 11 | 12 |
| 13 | 14 | 15 | 16 | 17 | 18 | 19 |
| 20 | 21 | 22 | 23 | 24 | 25 | 26 |
| 27 | 28 | 29 | 30 |


