# EIP 7702 **Published by:** [zoie](https://paragraph.com/@zoie/) **Published on:** 2025-06-09 **URL:** https://paragraph.com/@zoie/eip-7702 ## Content EIP-7702 是一项以太坊改进提案,旨在通过引入一种新的交易类型,使外部拥有账户(EOA)能够临时像智能合约账户一样运作。这项提案的目的是简化账户抽象,允许普通的 Web3 钱包能够实现智能钱包的某些功能。账户模型evm账户模型大概如下address => { Nonce uint64 Balance *uint256.Int Code []byte } 对于eoa账户,code里无代码,不具备合约功能 使用7702交易,eoa授权合约后, eoa账户下也会有code。跟eoa地址交互,是跟他的合约交互。 比如授权后,他的合约里没提供fallback方法,就无法收bnb 比如授权合约是一个工具类转出token,那其实每个人都可以调用他的方法转出token具体实现7702交易授权合约/取消授权合约,都需要通过7702的交易类型; 7702交易类型,为新增的一个交易类型。// SetCodeTx implements the EIP-7702 transaction type which temporarily installs // the code at the signer's address. type SetCodeTx struct { ChainID *uint256.Int Nonce uint64 GasTipCap *uint256.Int // a.k.a. maxPriorityFeePerGas GasFeeCap *uint256.Int // a.k.a. maxFeePerGas Gas uint64 To common.Address Value *uint256.Int Data []byte AccessList AccessList AuthList []SetCodeAuthorization // Signature values V *uint256.Int R *uint256.Int S *uint256.Int } // SetCodeAuthorization is an authorization from an account to deploy code at its address. type SetCodeAuthorization struct { ChainID uint256.Int `json:"chainId" gencodec:"required"` Address common.Address `json:"address" gencodec:"required"` Nonce uint64 `json:"nonce" gencodec:"required"` V uint8 `json:"yParity" gencodec:"required"` R uint256.Int `json:"r" gencodec:"required"` S uint256.Int `json:"s" gencodec:"required"` } 用户授权,需要对合约地址和用户nonce, chainid进行签名即可。EVM在执行交易前,先查看SetCodeAuthorizations, 设置code到用户地址下,再进行执行交易; 啊这里要注意点,要是applyAuthorization有error,这里是忽略error的if contractCreation { ret, _, st.gasRemaining, vmerr = st.evm.Create(sender, msg.Data, st.gasRemaining, value) } else { // Increment the nonce for the next transaction. st.state.SetNonce(msg.From, st.state.GetNonce(msg.From)+1, tracing.NonceChangeEoACall) // Apply EIP-7702 authorizations. if msg.SetCodeAuthorizations != nil { for _, auth := range msg.SetCodeAuthorizations { // Note errors are ignored, we simply skip invalid authorizations here. st.applyAuthorization(&auth) } } // Perform convenience warming of sender's delegation target. Although the // sender is already warmed in Prepare(..), it's possible a delegation to // the account was deployed during this transaction. To handle correctly, // simply wait until the final state of delegations is determined before // performing the resolution and warming. if addr, ok := types.ParseDelegation(st.state.GetCode(*msg.To)); ok { st.state.AddAddressToAccessList(addr) } // Execute the transaction's call. ret, st.gasRemaining, vmerr = st.evm.Call(sender, st.to(), msg.Data, st.gasRemaining, value) } 查询某账户是否是有授权//eth_getCode 返回值如果是 以 0xef010051510973ba7c1cc5a5e48e180c68b2ea4b9ec7df 0xef0100开头,那就是授权合约 合约地址就把前缀去掉就行 要取消,就签一笔address = common.Address{}的授权就行回到交易如果是自己签授权/取消授权,因为evm 里msg.from nonce先生效,所以auth里的nonce记得要➕1 最后放一个例子func TestCccD(t *testing.T) { ctx := context.Background() client, _ := ethclient.DialContext(ctx, "https://data-seed-prebsc-1-s1.bnbchain.org:8545") feeKey, _ := crypto.HexToECDSA("") feeAddress := crypto.PubkeyToAddress(feeKey.PublicKey) authKey, _ := crypto.HexToECDSA("") authAddress := crypto.PubkeyToAddress(authKey.PublicKey) authNonce, err := client.NonceAt(context.Background(), authAddress, nil) noErr(err) feeNonce, err := client.NonceAt(context.Background(), feeAddress, nil) noErr(err) fmt.Println("fee", feeAddress.String(), feeNonce) fmt.Println("auth", authAddress.String(), authNonce) chainId := uint256.NewInt(97) authList, err := types.SignSetCode(authKey, types.SetCodeAuthorization{ ChainID: *chainId, //Address: common.HexToAddress("0x51510973ba7c1cc5a5e48e180c68b2ea4b9ec7df"), Address: common.Address{}, Nonce: authNonce, }) //fmt.Println(authList, err) //authList.Address = common.HexToAddress("0x51510973ba8c1cc5a5e48e180c68b2ea4b9ec7df") //authList.Nonce = 123 data, err := hex.DecodeString("79f2447e000000000000000000000000ec5dcb5dbf4b114c9d0f65bccab49ec54f6a0867000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000eeae6c472be3ced42094b0f5a4f49380d0cfbccc000000000000000000000000eeae6c472be3ced42094b0f5a4f49380d0cfbccc0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000012c000000000000000000000000000000000000000000000000000000000000012c") noErr(err) tx := &types.SetCodeTx{ ChainID: chainId, Nonce: feeNonce, GasTipCap: uint256.NewInt(1e9), GasFeeCap: uint256.NewInt(1e9), Gas: 1000000, To: authAddress, Value: nil, Data: data, AccessList: nil, AuthList: []types.SetCodeAuthorization{authList}, } //fmt.Println(authList) // signedTx, err := types.SignTx(types.NewTx(tx), types.NewPragueSigner(big.NewInt(97)), feeKey) noErr(err) fmt.Println(signedTx.Type()) //tx := &types.LegacyTx{ // Nonce: feeNonce, // GasPrice: big.NewInt(1e9), // Gas: 100000, // To: &authAddress, // Value: nil, // Data: data, //} //signedTx, err := types.SignTx(types.NewTx(tx), types.NewEIP155Signer(big.NewInt(97)), feeKey) //noErr(err) fmt.Println(signedTx.Type()) err = client.SendTransaction(ctx, signedTx) noErr(err) fmt.Println(signedTx.Hash()) } ## Publication Information - [zoie](https://paragraph.com/@zoie/): Publication homepage - [All Posts](https://paragraph.com/@zoie/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@zoie): Subscribe to updates