github.com/ethereum-optimism/optimism@v1.7.2/packages/core-utils/src/optimism/encoding.ts (about) 1 import { BigNumberish, BigNumber } from '@ethersproject/bignumber' 2 import { Interface } from '@ethersproject/abi' 3 4 const iface = new Interface([ 5 'function relayMessage(address,address,bytes,uint256)', 6 'function relayMessage(uint256,address,address,uint256,uint256,bytes)', 7 ]) 8 9 const nonceMask = BigNumber.from( 10 '0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' 11 ) 12 13 /** 14 * Encodes the version into the nonce. 15 * 16 * @param nonce 17 * @param version 18 */ 19 export const encodeVersionedNonce = ( 20 nonce: BigNumber, 21 version: BigNumber 22 ): BigNumber => { 23 return version.or(nonce.shl(240)) 24 } 25 26 /** 27 * Decodes the version from the nonce and returns the unversioned nonce as well 28 * as the version. The version is encoded in the first byte of 29 * the nonce. Note that this nonce is the nonce held in the 30 * CrossDomainMessenger. 31 * 32 * @param nonce 33 */ 34 export const decodeVersionedNonce = ( 35 nonce: BigNumber 36 ): { 37 version: BigNumber 38 nonce: BigNumber 39 } => { 40 return { 41 version: nonce.shr(240), 42 nonce: nonce.and(nonceMask), 43 } 44 } 45 46 /** 47 * Encodes a V1 cross domain message. This message format was used before 48 * bedrock and does not support value transfer because ETH was represented as an 49 * ERC20 natively. 50 * 51 * @param target The target of the cross domain message 52 * @param sender The sender of the cross domain message 53 * @param data The data passed along with the cross domain message 54 * @param nonce The cross domain message nonce 55 */ 56 export const encodeCrossDomainMessageV0 = ( 57 target: string, 58 sender: string, 59 data: string, 60 nonce: BigNumber 61 ) => { 62 return iface.encodeFunctionData( 63 'relayMessage(address,address,bytes,uint256)', 64 [target, sender, data, nonce] 65 ) 66 } 67 68 /** 69 * Encodes a V1 cross domain message. This message format shipped with bedrock 70 * and supports value transfer with native ETH. 71 * 72 * @param nonce The cross domain message nonce 73 * @param sender The sender of the cross domain message 74 * @param target The target of the cross domain message 75 * @param value The value being sent with the cross domain message 76 * @param gasLimit The gas limit of the cross domain execution 77 * @param data The data passed along with the cross domain message 78 */ 79 export const encodeCrossDomainMessageV1 = ( 80 nonce: BigNumber, 81 sender: string, 82 target: string, 83 value: BigNumberish, 84 gasLimit: BigNumberish, 85 data: string 86 ) => { 87 return iface.encodeFunctionData( 88 'relayMessage(uint256,address,address,uint256,uint256,bytes)', 89 [nonce, sender, target, value, gasLimit, data] 90 ) 91 } 92 93 /** 94 * Encodes a cross domain message. The version byte in the nonce determines 95 * the serialization format that is used. 96 * 97 * @param nonce The cross domain message nonce 98 * @param sender The sender of the cross domain message 99 * @param target The target of the cross domain message 100 * @param value The value being sent with the cross domain message 101 * @param gasLimit The gas limit of the cross domain execution 102 * @param data The data passed along with the cross domain message 103 */ 104 export const encodeCrossDomainMessage = ( 105 nonce: BigNumber, 106 sender: string, 107 target: string, 108 value: BigNumber, 109 gasLimit: BigNumber, 110 data: string 111 ) => { 112 const { version } = decodeVersionedNonce(nonce) 113 if (version.eq(0)) { 114 return encodeCrossDomainMessageV0(target, sender, data, nonce) 115 } else if (version.eq(1)) { 116 return encodeCrossDomainMessageV1( 117 nonce, 118 sender, 119 target, 120 value, 121 gasLimit, 122 data 123 ) 124 } 125 throw new Error(`unknown version ${version.toString()}`) 126 }